Socket.cs 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746
  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. //
  8. // Copyright (C) 2001, 2002 Phillip Pearson and Ximian, Inc.
  9. // http://www.myelin.co.nz
  10. // (c) 2004 Novell, Inc. (http://www.novell.com)
  11. //
  12. //
  13. // Permission is hereby granted, free of charge, to any person obtaining
  14. // a copy of this software and associated documentation files (the
  15. // "Software"), to deal in the Software without restriction, including
  16. // without limitation the rights to use, copy, modify, merge, publish,
  17. // distribute, sublicense, and/or sell copies of the Software, and to
  18. // permit persons to whom the Software is furnished to do so, subject to
  19. // the following conditions:
  20. //
  21. // The above copyright notice and this permission notice shall be
  22. // included in all copies or substantial portions of the Software.
  23. //
  24. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  25. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  26. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  27. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  28. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  29. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  30. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  31. //
  32. using System;
  33. using System.Net;
  34. using System.Collections;
  35. using System.Runtime.CompilerServices;
  36. using System.Runtime.InteropServices;
  37. using System.Threading;
  38. using System.Reflection;
  39. using System.IO;
  40. namespace System.Net.Sockets
  41. {
  42. public class Socket : IDisposable
  43. {
  44. [StructLayout (LayoutKind.Sequential)]
  45. private sealed class SocketAsyncResult: IAsyncResult
  46. {
  47. /* Same structure in the runtime */
  48. public Socket Sock;
  49. IntPtr handle;
  50. object state;
  51. AsyncCallback callback;
  52. WaitHandle waithandle;
  53. Exception delayedException;
  54. public EndPoint EndPoint; // Connect,ReceiveFrom,SendTo
  55. public byte [] Buffer; // Receive,ReceiveFrom,Send,SendTo
  56. public int Offset; // Receive,ReceiveFrom,Send,SendTo
  57. public int Size; // Receive,ReceiveFrom,Send,SendTo
  58. public SocketFlags SockFlags; // Receive,ReceiveFrom,Send,SendTo
  59. // Return values
  60. Socket acc_socket;
  61. int total;
  62. bool completed_sync;
  63. bool completed;
  64. AsyncCallback real_callback;
  65. int error;
  66. public SocketAsyncResult (Socket sock, object state, AsyncCallback callback)
  67. {
  68. this.Sock = sock;
  69. this.handle = sock.socket;
  70. this.state = state;
  71. this.real_callback = callback;
  72. SockFlags = SocketFlags.None;
  73. }
  74. public void CreateAsyncDelegate ()
  75. {
  76. if (real_callback != null)
  77. this.callback = new AsyncCallback (FakeCB);
  78. }
  79. static void FakeCB (IAsyncResult result)
  80. {
  81. SocketAsyncResult ares = (SocketAsyncResult) result;
  82. ares.real_callback.BeginInvoke (ares, null, null);
  83. }
  84. public void CheckIfThrowDelayedException ()
  85. {
  86. if (delayedException != null)
  87. throw delayedException;
  88. if (error != 0)
  89. throw new SocketException (error);
  90. }
  91. public void Complete ()
  92. {
  93. IsCompleted = true;
  94. if (real_callback != null)
  95. real_callback (this);
  96. }
  97. public void Complete (int total)
  98. {
  99. this.total = total;
  100. Complete ();
  101. }
  102. public void Complete (Exception e)
  103. {
  104. delayedException = e;
  105. Complete ();
  106. }
  107. public void Complete (Socket s)
  108. {
  109. acc_socket = s;
  110. Complete ();
  111. }
  112. public object AsyncState {
  113. get {
  114. return state;
  115. }
  116. }
  117. public WaitHandle AsyncWaitHandle {
  118. get {
  119. lock (this) {
  120. if (waithandle == null)
  121. waithandle = new ManualResetEvent (completed);
  122. }
  123. return waithandle;
  124. }
  125. set {
  126. waithandle=value;
  127. }
  128. }
  129. public bool CompletedSynchronously {
  130. get {
  131. return(completed_sync);
  132. }
  133. }
  134. public bool IsCompleted {
  135. get {
  136. return(completed);
  137. }
  138. set {
  139. completed=value;
  140. lock (this) {
  141. if (waithandle != null && value) {
  142. ((ManualResetEvent) waithandle).Set ();
  143. }
  144. }
  145. }
  146. }
  147. public Socket Socket {
  148. get {
  149. return acc_socket;
  150. }
  151. }
  152. public int Total {
  153. get {
  154. return total;
  155. }
  156. }
  157. }
  158. private sealed class Worker
  159. {
  160. SocketAsyncResult result;
  161. public Worker (SocketAsyncResult ares)
  162. {
  163. this.result = ares;
  164. }
  165. public void Accept ()
  166. {
  167. lock (result) {
  168. Socket acc_socket = null;
  169. try {
  170. if (!result.Sock.blocking)
  171. result.Sock.Poll (-1, SelectMode.SelectRead);
  172. acc_socket = result.Sock.Accept ();
  173. } catch (Exception e) {
  174. result.Complete (e);
  175. return;
  176. }
  177. result.Complete (acc_socket);
  178. }
  179. }
  180. public void Connect ()
  181. {
  182. lock (result) {
  183. try {
  184. result.Sock.Connect (result.EndPoint);
  185. } catch (SocketException se) {
  186. if (result.Sock.blocking || se.ErrorCode != 10036) {
  187. result.Complete (se);
  188. return;
  189. }
  190. try {
  191. result.Sock.Poll (-1, SelectMode.SelectWrite);
  192. result.Sock.Connect (result.EndPoint);
  193. } catch (Exception k) {
  194. result.Complete (k);
  195. return;
  196. }
  197. } catch (Exception e) {
  198. result.Complete (e);
  199. return;
  200. }
  201. result.Complete ();
  202. }
  203. }
  204. public void Receive ()
  205. {
  206. lock (result) {
  207. int total = 0;
  208. try {
  209. if (!result.Sock.blocking)
  210. result.Sock.Poll (-1, SelectMode.SelectRead);
  211. total = result.Sock.Receive_nochecks (result.Buffer,
  212. result.Offset,
  213. result.Size,
  214. result.SockFlags);
  215. } catch (Exception e) {
  216. result.Complete (e);
  217. return;
  218. }
  219. result.Complete (total);
  220. }
  221. }
  222. public void ReceiveFrom ()
  223. {
  224. lock (result) {
  225. int total = 0;
  226. try {
  227. if (!result.Sock.blocking)
  228. result.Sock.Poll (-1, SelectMode.SelectRead);
  229. total = result.Sock.ReceiveFrom_nochecks (result.Buffer,
  230. result.Offset,
  231. result.Size,
  232. result.SockFlags,
  233. ref result.EndPoint);
  234. } catch (Exception e) {
  235. result.Complete (e);
  236. return;
  237. }
  238. result.Complete (total);
  239. }
  240. }
  241. public void Send ()
  242. {
  243. lock (result) {
  244. int total = 0;
  245. try {
  246. if (!result.Sock.blocking)
  247. result.Sock.Poll (-1, SelectMode.SelectWrite);
  248. total = result.Sock.Send_nochecks (result.Buffer,
  249. result.Offset,
  250. result.Size,
  251. result.SockFlags);
  252. } catch (Exception e) {
  253. result.Complete (e);
  254. return;
  255. }
  256. result.Complete (total);
  257. }
  258. }
  259. public void SendTo() {
  260. lock (result) {
  261. int total = 0;
  262. try {
  263. if (!result.Sock.blocking)
  264. result.Sock.Poll (-1, SelectMode.SelectWrite);
  265. total = result.Sock.SendTo_nochecks (result.Buffer,
  266. result.Offset,
  267. result.Size,
  268. result.SockFlags,
  269. result.EndPoint);
  270. } catch (Exception e) {
  271. result.Complete (e);
  272. return;
  273. }
  274. result.Complete (total);
  275. }
  276. }
  277. }
  278. /* the field "socket" is looked up by name by the runtime */
  279. private IntPtr socket;
  280. private AddressFamily address_family;
  281. private SocketType socket_type;
  282. private ProtocolType protocol_type;
  283. internal bool blocking=true;
  284. private int pendingEnds;
  285. private int closeDelayed;
  286. static readonly bool supportsAsync = FakeGetSupportsAsync ();
  287. delegate void SocketAsyncCall ();
  288. /*
  289. * These two fields are looked up by name by the runtime, don't change
  290. * their name without also updating the runtime code.
  291. */
  292. private static int ipv4Supported = -1, ipv6Supported = -1;
  293. /* When true, the socket was connected at the time of
  294. * the last IO operation
  295. */
  296. private bool connected=false;
  297. /* true if we called Close_internal */
  298. private bool closed;
  299. /* Used in LocalEndPoint and RemoteEndPoint if the
  300. * Mono.Posix assembly is available
  301. */
  302. private static object unixendpoint=null;
  303. private static Type unixendpointtype=null;
  304. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  305. private extern static void Select_internal(ref Socket[] read,
  306. ref Socket[] write,
  307. ref Socket[] err,
  308. int timeout,
  309. out int error);
  310. public static void Select(IList read_list, IList write_list,
  311. IList err_list, int time_us) {
  312. int read_count = 0, write_count = 0, err_count = 0;
  313. Socket[] read_arr = null;
  314. Socket[] write_arr = null;
  315. Socket[] err_arr = null;
  316. if (read_list!=null)
  317. read_count=read_list.Count;
  318. if (read_count != 0)
  319. read_arr=new Socket[read_count];
  320. if (write_list!=null)
  321. write_count=write_list.Count;
  322. if (write_count != 0)
  323. write_arr=new Socket[write_count];
  324. if (err_list!=null)
  325. err_count=err_list.Count;
  326. if (err_count != 0)
  327. err_arr=new Socket[err_count];
  328. if(read_count == 0 && write_count == 0 && err_count == 0) {
  329. throw new ArgumentNullException ("read_list, write_list, err_list",
  330. "All the lists are null or empty.");
  331. }
  332. int i;
  333. if (read_count != 0) {
  334. i=0;
  335. foreach (Socket s in read_list) {
  336. read_arr[i]=s;
  337. i++;
  338. }
  339. }
  340. if (write_count != 0) {
  341. i=0;
  342. foreach (Socket s in write_list) {
  343. write_arr[i]=s;
  344. i++;
  345. }
  346. }
  347. if (err_count != 0) {
  348. i=0;
  349. foreach (Socket s in err_list) {
  350. err_arr[i]=s;
  351. i++;
  352. }
  353. }
  354. int error;
  355. Select_internal(ref read_arr, ref write_arr,
  356. ref err_arr, time_us, out error);
  357. if(error != 0) {
  358. throw new SocketException (error);
  359. }
  360. /* Make sure the connected state is updated
  361. * for each socket returned from the select;
  362. * for non blocking Connect()s, this is when
  363. * we find out that the connect succeeded.
  364. */
  365. if(read_list!=null) {
  366. read_list.Clear();
  367. if (read_arr != null) {
  368. for(i=0; i<read_arr.Length; i++) {
  369. read_list.Add(read_arr[i]);
  370. read_arr[i].connected = true;
  371. }
  372. }
  373. }
  374. if(write_list!=null) {
  375. write_list.Clear();
  376. if (write_arr != null) {
  377. for(i=0; i<write_arr.Length; i++) {
  378. write_list.Add(write_arr[i]);
  379. write_arr[i].connected = true;
  380. }
  381. }
  382. }
  383. if(err_list!=null) {
  384. err_list.Clear();
  385. if (err_arr != null) {
  386. for(i=0; i<err_arr.Length; i++) {
  387. err_list.Add(err_arr[i]);
  388. err_arr[i].connected = true;
  389. }
  390. }
  391. }
  392. }
  393. static Socket() {
  394. Assembly ass;
  395. try {
  396. ass = Assembly.Load (Consts.AssemblyMono_Posix);
  397. } catch (FileNotFoundException) {
  398. return;
  399. }
  400. unixendpointtype=ass.GetType("Mono.Posix.UnixEndPoint");
  401. /* The endpoint Create() method is an instance
  402. * method :-(
  403. */
  404. Type[] arg_types=new Type[1];
  405. arg_types[0]=typeof(string);
  406. ConstructorInfo cons=unixendpointtype.GetConstructor(arg_types);
  407. object[] args=new object[1];
  408. args[0]="";
  409. unixendpoint=cons.Invoke(args);
  410. }
  411. // private constructor used by Accept, which already
  412. // has a socket handle to use
  413. private Socket(AddressFamily family, SocketType type,
  414. ProtocolType proto, IntPtr sock) {
  415. address_family=family;
  416. socket_type=type;
  417. protocol_type=proto;
  418. socket=sock;
  419. connected=true;
  420. }
  421. // Creates a new system socket, returning the handle
  422. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  423. private extern IntPtr Socket_internal(AddressFamily family,
  424. SocketType type,
  425. ProtocolType proto,
  426. out int error);
  427. public Socket(AddressFamily family, SocketType type,
  428. ProtocolType proto) {
  429. address_family=family;
  430. socket_type=type;
  431. protocol_type=proto;
  432. int error;
  433. socket=Socket_internal(family, type, proto, out error);
  434. if (error != 0) {
  435. throw new SocketException (error);
  436. }
  437. }
  438. public AddressFamily AddressFamily {
  439. get {
  440. return(address_family);
  441. }
  442. }
  443. // Returns the amount of data waiting to be read on socket
  444. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  445. private extern static int Available_internal(IntPtr socket,
  446. out int error);
  447. public int Available {
  448. get {
  449. if (disposed && closed)
  450. throw new ObjectDisposedException (GetType ().ToString ());
  451. int ret, error;
  452. ret = Available_internal(socket, out error);
  453. if (error != 0) {
  454. throw new SocketException (error);
  455. }
  456. return(ret);
  457. }
  458. }
  459. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  460. private extern static void Blocking_internal(IntPtr socket,
  461. bool block,
  462. out int error);
  463. public bool Blocking {
  464. get {
  465. return(blocking);
  466. }
  467. set {
  468. int error;
  469. Blocking_internal(socket, value, out error);
  470. if (error != 0) {
  471. throw new SocketException (error);
  472. }
  473. blocking=value;
  474. }
  475. }
  476. public bool Connected {
  477. get {
  478. return(connected);
  479. }
  480. }
  481. public IntPtr Handle {
  482. get {
  483. return(socket);
  484. }
  485. }
  486. // Returns the local endpoint details in addr and port
  487. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  488. private extern static SocketAddress LocalEndPoint_internal(IntPtr socket, out int error);
  489. [MonoTODO("Support non-IP endpoints")]
  490. public EndPoint LocalEndPoint {
  491. get {
  492. if (disposed && closed)
  493. throw new ObjectDisposedException (GetType ().ToString ());
  494. SocketAddress sa;
  495. int error;
  496. sa=LocalEndPoint_internal(socket, out error);
  497. if (error != 0) {
  498. throw new SocketException (error);
  499. }
  500. if(sa.Family==AddressFamily.InterNetwork || sa.Family==AddressFamily.InterNetworkV6) {
  501. // Stupidly, EndPoint.Create() is an
  502. // instance method
  503. return new IPEndPoint(0, 0).Create(sa);
  504. } else if (sa.Family==AddressFamily.Unix &&
  505. unixendpoint!=null) {
  506. return((EndPoint)unixendpointtype.InvokeMember("Create", BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public, null, unixendpoint, new object[] {sa}));
  507. } else {
  508. throw new NotImplementedException();
  509. }
  510. }
  511. }
  512. public ProtocolType ProtocolType {
  513. get {
  514. return(protocol_type);
  515. }
  516. }
  517. // Returns the remote endpoint details in addr and port
  518. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  519. private extern static SocketAddress RemoteEndPoint_internal(IntPtr socket, out int error);
  520. [MonoTODO("Support non-IP endpoints")]
  521. public EndPoint RemoteEndPoint {
  522. get {
  523. if (disposed && closed)
  524. throw new ObjectDisposedException (GetType ().ToString ());
  525. SocketAddress sa;
  526. int error;
  527. sa=RemoteEndPoint_internal(socket, out error);
  528. if (error != 0) {
  529. throw new SocketException (error);
  530. }
  531. if(sa.Family==AddressFamily.InterNetwork || sa.Family==AddressFamily.InterNetworkV6 ) {
  532. // Stupidly, EndPoint.Create() is an
  533. // instance method
  534. return new IPEndPoint(0, 0).Create(sa);
  535. } else if (sa.Family==AddressFamily.Unix &&
  536. unixendpoint!=null) {
  537. return((EndPoint)unixendpointtype.InvokeMember("Create", BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public, null, unixendpoint, new object[] {sa}));
  538. } else {
  539. throw new NotImplementedException();
  540. }
  541. }
  542. }
  543. public SocketType SocketType {
  544. get {
  545. return(socket_type);
  546. }
  547. }
  548. #if NET_1_1
  549. public static bool SupportsIPv4 {
  550. get {
  551. CheckProtocolSupport();
  552. return ipv4Supported == 1;
  553. }
  554. }
  555. public static bool SupportsIPv6 {
  556. get {
  557. CheckProtocolSupport();
  558. return ipv6Supported == 1;
  559. }
  560. }
  561. #else
  562. internal static bool SupportsIPv4
  563. {
  564. get
  565. {
  566. return true;
  567. }
  568. }
  569. internal static bool SupportsIPv6
  570. {
  571. get
  572. {
  573. return false;
  574. }
  575. }
  576. #endif
  577. internal static void CheckProtocolSupport()
  578. {
  579. if(ipv4Supported == -1) {
  580. try {
  581. Socket tmp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  582. tmp.Close();
  583. ipv4Supported = 1;
  584. }
  585. catch {
  586. ipv4Supported = 0;
  587. }
  588. }
  589. if(ipv6Supported == -1) {
  590. NetConfig config = (NetConfig)System.Configuration.ConfigurationSettings.GetConfig("system.net/settings");
  591. if(config != null)
  592. ipv6Supported = config.ipv6Enabled?-1:0;
  593. if(ipv6Supported != 0) {
  594. try {
  595. Socket tmp = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
  596. tmp.Close();
  597. ipv6Supported = 1;
  598. }
  599. catch { }
  600. }
  601. }
  602. }
  603. // Creates a new system socket, returning the handle
  604. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  605. private extern static IntPtr Accept_internal(IntPtr sock,
  606. out int error);
  607. public Socket Accept() {
  608. if (disposed && closed)
  609. throw new ObjectDisposedException (GetType ().ToString ());
  610. int error;
  611. IntPtr sock=Accept_internal(socket, out error);
  612. if (!blocking && error == 10035) {
  613. Poll (-1, SelectMode.SelectRead);
  614. sock = Accept_internal (socket, out error);
  615. }
  616. if (error != 0) {
  617. throw new SocketException (error);
  618. }
  619. Socket accepted = new Socket(this.AddressFamily,
  620. this.SocketType,
  621. this.ProtocolType, sock);
  622. // The MS runtime (really the OS, we suspect)
  623. // sets newly accepted sockets to have the
  624. // same Blocking status as the listening
  625. // socket
  626. accepted.Blocking = this.Blocking;
  627. return(accepted);
  628. }
  629. public IAsyncResult BeginAccept(AsyncCallback callback,
  630. object state) {
  631. if (disposed && closed)
  632. throw new ObjectDisposedException (GetType ().ToString ());
  633. Interlocked.Increment (ref pendingEnds);
  634. SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
  635. Worker worker = new Worker (req);
  636. SocketAsyncCall sac = new SocketAsyncCall (worker.Accept);
  637. sac.BeginInvoke (null, null);
  638. return(req);
  639. }
  640. public IAsyncResult BeginConnect(EndPoint end_point,
  641. AsyncCallback callback,
  642. object state) {
  643. if (disposed && closed)
  644. throw new ObjectDisposedException (GetType ().ToString ());
  645. if (end_point == null)
  646. throw new ArgumentNullException ("end_point");
  647. Interlocked.Increment (ref pendingEnds);
  648. SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
  649. req.EndPoint = end_point;
  650. Worker worker = new Worker (req);
  651. SocketAsyncCall sac = new SocketAsyncCall (worker.Connect);
  652. sac.BeginInvoke (null, null);
  653. return(req);
  654. }
  655. public IAsyncResult BeginReceive(byte[] buffer, int offset,
  656. int size,
  657. SocketFlags socket_flags,
  658. AsyncCallback callback,
  659. object state) {
  660. if (disposed && closed)
  661. throw new ObjectDisposedException (GetType ().ToString ());
  662. if (buffer == null)
  663. throw new ArgumentNullException ("buffer");
  664. if (offset < 0 || offset > buffer.Length)
  665. throw new ArgumentOutOfRangeException ("offset");
  666. if (size < 0 || offset + size > buffer.Length)
  667. throw new ArgumentOutOfRangeException ("size");
  668. Interlocked.Increment (ref pendingEnds);
  669. SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
  670. req.Buffer = buffer;
  671. req.Offset = offset;
  672. req.Size = size;
  673. req.SockFlags = socket_flags;
  674. if (supportsAsync && socket_type == SocketType.Stream) {
  675. int error;
  676. req.CreateAsyncDelegate ();
  677. KeepReference (req);
  678. AsyncReceiveInternal (req, out error);
  679. if (error != 0 && error != 10036) // WSAEINPROGRESS
  680. throw new SocketException (error);
  681. } else {
  682. Worker worker = new Worker (req);
  683. SocketAsyncCall sac = new SocketAsyncCall (worker.Receive);
  684. sac.BeginInvoke (null, null);
  685. }
  686. return req;
  687. }
  688. public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset,
  689. int size,
  690. SocketFlags socket_flags,
  691. ref EndPoint remote_end,
  692. AsyncCallback callback,
  693. object state) {
  694. if (disposed && closed)
  695. throw new ObjectDisposedException (GetType ().ToString ());
  696. if (buffer == null)
  697. throw new ArgumentNullException ("buffer");
  698. if (offset < 0)
  699. throw new ArgumentOutOfRangeException ("offset must be >= 0");
  700. if (size < 0)
  701. throw new ArgumentOutOfRangeException ("size must be >= 0");
  702. if (offset + size > buffer.Length)
  703. throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
  704. Interlocked.Increment (ref pendingEnds);
  705. SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
  706. req.Buffer = buffer;
  707. req.Offset = offset;
  708. req.Size = size;
  709. req.SockFlags = socket_flags;
  710. req.EndPoint = remote_end;
  711. Worker worker = new Worker (req);
  712. SocketAsyncCall sac = new SocketAsyncCall (worker.ReceiveFrom);
  713. sac.BeginInvoke (null, null);
  714. return req;
  715. }
  716. public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socket_flags,
  717. AsyncCallback callback, object state)
  718. {
  719. if (disposed && closed)
  720. throw new ObjectDisposedException (GetType ().ToString ());
  721. if (buffer == null)
  722. throw new ArgumentNullException ("buffer");
  723. if (offset < 0)
  724. throw new ArgumentOutOfRangeException ("offset must be >= 0");
  725. if (size < 0)
  726. throw new ArgumentOutOfRangeException ("size must be >= 0");
  727. if (offset + size > buffer.Length)
  728. throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
  729. Interlocked.Increment (ref pendingEnds);
  730. SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
  731. req.Buffer = buffer;
  732. req.Offset = offset;
  733. req.Size = size;
  734. req.SockFlags = socket_flags;
  735. if (supportsAsync && socket_type == SocketType.Stream) {
  736. int error;
  737. req.CreateAsyncDelegate ();
  738. KeepReference (req);
  739. AsyncSendInternal (req, out error);
  740. if (error != 0 && error != 10036) // WSAEINPROGRESS
  741. throw new SocketException (error);
  742. } else {
  743. Worker worker = new Worker (req);
  744. SocketAsyncCall sac = new SocketAsyncCall (worker.Send);
  745. sac.BeginInvoke (null, null);
  746. }
  747. return req;
  748. }
  749. public IAsyncResult BeginSendTo(byte[] buffer, int offset,
  750. int size,
  751. SocketFlags socket_flags,
  752. EndPoint remote_end,
  753. AsyncCallback callback,
  754. object state) {
  755. if (disposed && closed)
  756. throw new ObjectDisposedException (GetType ().ToString ());
  757. if (buffer == null)
  758. throw new ArgumentNullException ("buffer");
  759. if (offset < 0)
  760. throw new ArgumentOutOfRangeException ("offset must be >= 0");
  761. if (size < 0)
  762. throw new ArgumentOutOfRangeException ("size must be >= 0");
  763. if (offset + size > buffer.Length)
  764. throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
  765. Interlocked.Increment (ref pendingEnds);
  766. SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
  767. req.Buffer = buffer;
  768. req.Offset = offset;
  769. req.Size = size;
  770. req.SockFlags = socket_flags;
  771. req.EndPoint = remote_end;
  772. Worker worker = new Worker(req);
  773. SocketAsyncCall sac = new SocketAsyncCall (worker.SendTo);
  774. sac.BeginInvoke (null, null);
  775. return req;
  776. }
  777. // Creates a new system socket, returning the handle
  778. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  779. private extern static void Bind_internal(IntPtr sock,
  780. SocketAddress sa,
  781. out int error);
  782. public void Bind(EndPoint local_end) {
  783. if (disposed && closed)
  784. throw new ObjectDisposedException (GetType ().ToString ());
  785. if(local_end==null) {
  786. throw new ArgumentNullException("local_end");
  787. }
  788. int error;
  789. Bind_internal(socket, local_end.Serialize(),
  790. out error);
  791. if (error != 0) {
  792. throw new SocketException (error);
  793. }
  794. }
  795. // Closes the socket
  796. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  797. private extern static void Close_internal(IntPtr socket,
  798. out int error);
  799. public void Close() {
  800. ((IDisposable) this).Dispose ();
  801. }
  802. // Connects to the remote address
  803. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  804. private extern static void Connect_internal(IntPtr sock,
  805. SocketAddress sa,
  806. out int error);
  807. public void Connect(EndPoint remote_end) {
  808. if (disposed && closed)
  809. throw new ObjectDisposedException (GetType ().ToString ());
  810. if(remote_end==null) {
  811. throw new ArgumentNullException("remote_end");
  812. }
  813. int error;
  814. SocketAddress serial = remote_end.Serialize ();
  815. Connect_internal(socket, serial, out error);
  816. if (!blocking && error == 10035) {
  817. Poll (-1, SelectMode.SelectWrite);
  818. Connect_internal (socket, serial, out error);
  819. }
  820. if (error != 0)
  821. throw new SocketException (error);
  822. connected=true;
  823. }
  824. public Socket EndAccept(IAsyncResult result) {
  825. if (disposed && closed)
  826. throw new ObjectDisposedException (GetType ().ToString ());
  827. if (result == null)
  828. throw new ArgumentNullException ("result");
  829. SocketAsyncResult req = result as SocketAsyncResult;
  830. if (req == null)
  831. throw new ArgumentException ("Invalid IAsyncResult", "result");
  832. if (!result.IsCompleted)
  833. result.AsyncWaitHandle.WaitOne();
  834. Interlocked.Decrement (ref pendingEnds);
  835. CheckIfClose ();
  836. req.CheckIfThrowDelayedException();
  837. return req.Socket;
  838. }
  839. public void EndConnect(IAsyncResult result) {
  840. if (disposed && closed)
  841. throw new ObjectDisposedException (GetType ().ToString ());
  842. if (result == null)
  843. throw new ArgumentNullException ("result");
  844. SocketAsyncResult req = result as SocketAsyncResult;
  845. if (req == null)
  846. throw new ArgumentException ("Invalid IAsyncResult", "result");
  847. if (!result.IsCompleted)
  848. result.AsyncWaitHandle.WaitOne();
  849. Interlocked.Decrement (ref pendingEnds);
  850. CheckIfClose ();
  851. req.CheckIfThrowDelayedException();
  852. }
  853. public int EndReceive(IAsyncResult result) {
  854. if (disposed && closed)
  855. throw new ObjectDisposedException (GetType ().ToString ());
  856. if (result == null)
  857. throw new ArgumentNullException ("result");
  858. SocketAsyncResult req = result as SocketAsyncResult;
  859. if (req == null)
  860. throw new ArgumentException ("Invalid IAsyncResult", "result");
  861. if (supportsAsync && socket_type == SocketType.Stream)
  862. RemoveReference (req);
  863. if (!result.IsCompleted)
  864. result.AsyncWaitHandle.WaitOne();
  865. Interlocked.Decrement (ref pendingEnds);
  866. CheckIfClose ();
  867. req.CheckIfThrowDelayedException();
  868. return req.Total;
  869. }
  870. public int EndReceiveFrom(IAsyncResult result,
  871. ref EndPoint end_point) {
  872. if (disposed && closed)
  873. throw new ObjectDisposedException (GetType ().ToString ());
  874. if (result == null)
  875. throw new ArgumentNullException ("result");
  876. SocketAsyncResult req = result as SocketAsyncResult;
  877. if (req == null)
  878. throw new ArgumentException ("Invalid IAsyncResult", "result");
  879. if (!result.IsCompleted)
  880. result.AsyncWaitHandle.WaitOne();
  881. Interlocked.Decrement (ref pendingEnds);
  882. CheckIfClose ();
  883. req.CheckIfThrowDelayedException();
  884. end_point = req.EndPoint;
  885. return req.Total;
  886. }
  887. public int EndSend(IAsyncResult result) {
  888. if (disposed && closed)
  889. throw new ObjectDisposedException (GetType ().ToString ());
  890. if (result == null)
  891. throw new ArgumentNullException ("result");
  892. SocketAsyncResult req = result as SocketAsyncResult;
  893. if (req == null)
  894. throw new ArgumentException ("Invalid IAsyncResult", "result");
  895. if (supportsAsync && socket_type == SocketType.Stream)
  896. RemoveReference (req);
  897. if (!result.IsCompleted)
  898. result.AsyncWaitHandle.WaitOne();
  899. Interlocked.Decrement (ref pendingEnds);
  900. CheckIfClose ();
  901. req.CheckIfThrowDelayedException();
  902. return req.Total;
  903. }
  904. public int EndSendTo(IAsyncResult result) {
  905. if (disposed && closed)
  906. throw new ObjectDisposedException (GetType ().ToString ());
  907. if (result == null)
  908. throw new ArgumentNullException ("result");
  909. SocketAsyncResult req = result as SocketAsyncResult;
  910. if (req == null)
  911. throw new ArgumentException ("Invalid IAsyncResult", "result");
  912. if (!result.IsCompleted)
  913. result.AsyncWaitHandle.WaitOne();
  914. Interlocked.Decrement (ref pendingEnds);
  915. CheckIfClose ();
  916. req.CheckIfThrowDelayedException();
  917. return req.Total;
  918. }
  919. void CheckIfClose ()
  920. {
  921. if (Interlocked.CompareExchange (ref closeDelayed, 0, 1) == 1 &&
  922. Interlocked.CompareExchange (ref pendingEnds, 0, 0) == 0) {
  923. closed = true;
  924. int error;
  925. Close_internal(socket, out error);
  926. if (error != 0) {
  927. throw new SocketException (error);
  928. }
  929. }
  930. }
  931. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  932. private extern static void GetSocketOption_obj_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, out object obj_val, out int error);
  933. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  934. private extern static void GetSocketOption_arr_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val, out int error);
  935. public object GetSocketOption(SocketOptionLevel level,
  936. SocketOptionName name) {
  937. object obj_val;
  938. int error;
  939. GetSocketOption_obj_internal(socket, level, name,
  940. out obj_val, out error);
  941. if (error != 0) {
  942. throw new SocketException (error);
  943. }
  944. if(name==SocketOptionName.Linger) {
  945. return((LingerOption)obj_val);
  946. } else if (name==SocketOptionName.AddMembership ||
  947. name==SocketOptionName.DropMembership) {
  948. return((MulticastOption)obj_val);
  949. } else if (obj_val is int) {
  950. return((int)obj_val);
  951. } else {
  952. return(obj_val);
  953. }
  954. }
  955. public void GetSocketOption(SocketOptionLevel level,
  956. SocketOptionName name,
  957. byte[] opt_value) {
  958. int opt_value_len=opt_value.Length;
  959. int error;
  960. GetSocketOption_arr_internal(socket, level, name,
  961. ref opt_value, out error);
  962. if (error != 0) {
  963. throw new SocketException (error);
  964. }
  965. }
  966. public byte[] GetSocketOption(SocketOptionLevel level,
  967. SocketOptionName name,
  968. int length) {
  969. byte[] byte_val=new byte[length];
  970. int error;
  971. GetSocketOption_arr_internal(socket, level, name,
  972. ref byte_val, out error);
  973. if (error != 0) {
  974. throw new SocketException (error);
  975. }
  976. return(byte_val);
  977. }
  978. // See Socket.IOControl, WSAIoctl documentation in MSDN. The
  979. // common options between UNIX and Winsock are FIONREAD,
  980. // FIONBIO and SIOCATMARK. Anything else will depend on the
  981. // system.
  982. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  983. extern static int WSAIoctl (IntPtr sock, int ioctl_code,
  984. byte [] input, byte [] output,
  985. out int error);
  986. public int IOControl (int ioctl_code, byte [] in_value, byte [] out_value)
  987. {
  988. if (disposed)
  989. throw new ObjectDisposedException (GetType ().ToString ());
  990. int error;
  991. int result = WSAIoctl (socket, ioctl_code, in_value,
  992. out_value, out error);
  993. if (error != 0) {
  994. throw new SocketException (error);
  995. }
  996. if (result == -1)
  997. throw new InvalidOperationException ("Must use Blocking property instead.");
  998. return result;
  999. }
  1000. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1001. private extern static void Listen_internal(IntPtr sock,
  1002. int backlog,
  1003. out int error);
  1004. public void Listen(int backlog) {
  1005. int error;
  1006. Listen_internal(socket, backlog, out error);
  1007. if (error != 0) {
  1008. throw new SocketException (error);
  1009. }
  1010. }
  1011. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1012. extern static bool Poll_internal (IntPtr socket, SelectMode mode, int timeout, out int error);
  1013. public bool Poll (int time_us, SelectMode mode)
  1014. {
  1015. if (mode != SelectMode.SelectRead &&
  1016. mode != SelectMode.SelectWrite &&
  1017. mode != SelectMode.SelectError)
  1018. throw new NotSupportedException ("'mode' parameter is not valid.");
  1019. int error;
  1020. bool result = Poll_internal (socket, mode, time_us, out error);
  1021. if (error != 0)
  1022. throw new SocketException (error);
  1023. if (result == true) {
  1024. /* Update the connected state; for
  1025. * non-blocking Connect()s this is
  1026. * when we can find out that the
  1027. * connect succeeded.
  1028. */
  1029. connected = true;
  1030. }
  1031. return result;
  1032. }
  1033. public int Receive (byte [] buf)
  1034. {
  1035. if (buf == null)
  1036. throw new ArgumentNullException ("buf");
  1037. return Receive_nochecks (buf, 0, buf.Length, SocketFlags.None);
  1038. }
  1039. public int Receive (byte [] buf, SocketFlags flags)
  1040. {
  1041. if (buf == null)
  1042. throw new ArgumentNullException ("buf");
  1043. return Receive_nochecks (buf, 0, buf.Length, flags);
  1044. }
  1045. public int Receive (byte [] buf, int size, SocketFlags flags)
  1046. {
  1047. if (buf == null)
  1048. throw new ArgumentNullException ("buf");
  1049. if (size < 0 || size > buf.Length)
  1050. throw new ArgumentOutOfRangeException ("size");
  1051. return Receive_nochecks (buf, 0, size, flags);
  1052. }
  1053. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1054. private extern static int Receive_internal(IntPtr sock,
  1055. byte[] buffer,
  1056. int offset,
  1057. int count,
  1058. SocketFlags flags,
  1059. out int error);
  1060. public int Receive (byte [] buf, int offset, int size, SocketFlags flags)
  1061. {
  1062. if (buf == null)
  1063. throw new ArgumentNullException ("buf");
  1064. if (offset < 0 || offset > buf.Length)
  1065. throw new ArgumentOutOfRangeException ("offset");
  1066. if (size < 0 || offset + size > buf.Length)
  1067. throw new ArgumentOutOfRangeException ("size");
  1068. return Receive_nochecks (buf, offset, size, flags);
  1069. }
  1070. int Receive_nochecks (byte [] buf, int offset, int size, SocketFlags flags)
  1071. {
  1072. int ret, error;
  1073. ret = Receive_internal (socket, buf, offset, size, flags, out error);
  1074. if (error != 0) {
  1075. if (error != 10035 && error != 10036) // WSAEWOULDBLOCK && WSAEINPROGRESS
  1076. connected = false;
  1077. throw new SocketException (error);
  1078. }
  1079. connected = true;
  1080. return ret;
  1081. }
  1082. public int ReceiveFrom (byte [] buf, ref EndPoint remote_end)
  1083. {
  1084. if (buf == null)
  1085. throw new ArgumentNullException ("buf");
  1086. if (remote_end == null)
  1087. throw new ArgumentNullException ("remote_end");
  1088. return ReceiveFrom_nochecks (buf, 0, buf.Length, SocketFlags.None, ref remote_end);
  1089. }
  1090. public int ReceiveFrom (byte [] buf, SocketFlags flags, ref EndPoint remote_end)
  1091. {
  1092. if (buf == null)
  1093. throw new ArgumentNullException ("buf");
  1094. if (remote_end == null)
  1095. throw new ArgumentNullException ("remote_end");
  1096. return ReceiveFrom_nochecks (buf, 0, buf.Length, flags, ref remote_end);
  1097. }
  1098. public int ReceiveFrom (byte [] buf, int size, SocketFlags flags,
  1099. ref EndPoint remote_end)
  1100. {
  1101. if (buf == null)
  1102. throw new ArgumentNullException ("buf");
  1103. if (remote_end == null)
  1104. throw new ArgumentNullException ("remote_end");
  1105. if (size < 0 || size > buf.Length)
  1106. throw new ArgumentOutOfRangeException ("size");
  1107. return ReceiveFrom_nochecks (buf, 0, size, flags, ref remote_end);
  1108. }
  1109. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1110. private extern static int RecvFrom_internal(IntPtr sock,
  1111. byte[] buffer,
  1112. int offset,
  1113. int count,
  1114. SocketFlags flags,
  1115. ref SocketAddress sockaddr,
  1116. out int error);
  1117. public int ReceiveFrom (byte [] buf, int offset, int size, SocketFlags flags,
  1118. ref EndPoint remote_end)
  1119. {
  1120. if (buf == null)
  1121. throw new ArgumentNullException ("buf");
  1122. if (remote_end == null)
  1123. throw new ArgumentNullException ("remote_end");
  1124. if (offset < 0 || offset > buf.Length)
  1125. throw new ArgumentOutOfRangeException ("offset");
  1126. if (size < 0 || offset + size > buf.Length)
  1127. throw new ArgumentOutOfRangeException ("size");
  1128. return ReceiveFrom_nochecks (buf, offset, size, flags, ref remote_end);
  1129. }
  1130. int ReceiveFrom_nochecks (byte [] buf, int offset, int size, SocketFlags flags,
  1131. ref EndPoint remote_end)
  1132. {
  1133. SocketAddress sockaddr = remote_end.Serialize();
  1134. int cnt, error;
  1135. cnt = RecvFrom_internal (socket, buf, offset, size, flags, ref sockaddr, out error);
  1136. if (error != 0) {
  1137. if (error != 10035 && error != 10036) // WSAEWOULDBLOCK && WSAEINPROGRESS
  1138. connected = false;
  1139. throw new SocketException (error);
  1140. }
  1141. connected = true;
  1142. // If sockaddr is null then we're a connection
  1143. // oriented protocol and should ignore the
  1144. // remote_end parameter (see MSDN
  1145. // documentation for Socket.ReceiveFrom(...) )
  1146. if ( sockaddr != null ) {
  1147. // Stupidly, EndPoint.Create() is an
  1148. // instance method
  1149. remote_end = remote_end.Create (sockaddr);
  1150. }
  1151. return cnt;
  1152. }
  1153. public int Send (byte [] buf)
  1154. {
  1155. if (buf == null)
  1156. throw new ArgumentNullException ("buf");
  1157. return Send_nochecks (buf, 0, buf.Length, SocketFlags.None);
  1158. }
  1159. public int Send (byte [] buf, SocketFlags flags)
  1160. {
  1161. if (buf == null)
  1162. throw new ArgumentNullException ("buf");
  1163. return Send_nochecks (buf, 0, buf.Length, flags);
  1164. }
  1165. public int Send (byte [] buf, int size, SocketFlags flags)
  1166. {
  1167. if (buf == null)
  1168. throw new ArgumentNullException ("buf");
  1169. if (size < 0 || size > buf.Length)
  1170. throw new ArgumentOutOfRangeException ("size");
  1171. return Send_nochecks (buf, 0, size, flags);
  1172. }
  1173. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1174. private extern static int Send_internal(IntPtr sock,
  1175. byte[] buf, int offset,
  1176. int count,
  1177. SocketFlags flags,
  1178. out int error);
  1179. public int Send (byte [] buf, int offset, int size, SocketFlags flags)
  1180. {
  1181. if (buf == null)
  1182. throw new ArgumentNullException ("buffer");
  1183. if (offset < 0 || offset > buf.Length)
  1184. throw new ArgumentOutOfRangeException ("offset");
  1185. if (size < 0 || offset + size > buf.Length)
  1186. throw new ArgumentOutOfRangeException ("size");
  1187. return Send_nochecks (buf, offset, size, flags);
  1188. }
  1189. int Send_nochecks (byte [] buf, int offset, int size, SocketFlags flags)
  1190. {
  1191. if (size == 0)
  1192. return 0;
  1193. int ret, error;
  1194. ret = Send_internal (socket, buf, offset, size, flags, out error);
  1195. if (error != 0) {
  1196. if (error != 10035 && error != 10036) // WSAEWOULDBLOCK && WSAEINPROGRESS
  1197. connected = false;
  1198. throw new SocketException (error);
  1199. }
  1200. connected = true;
  1201. return ret;
  1202. }
  1203. public int SendTo (byte [] buffer, EndPoint remote_end)
  1204. {
  1205. if (buffer == null)
  1206. throw new ArgumentNullException ("buffer");
  1207. if (remote_end == null)
  1208. throw new ArgumentNullException ("remote_end");
  1209. return SendTo_nochecks (buffer, 0, buffer.Length, SocketFlags.None, remote_end);
  1210. }
  1211. public int SendTo (byte [] buffer, SocketFlags flags, EndPoint remote_end)
  1212. {
  1213. if (buffer == null)
  1214. throw new ArgumentNullException ("buffer");
  1215. if (remote_end == null)
  1216. throw new ArgumentNullException ("remote_end");
  1217. return SendTo_nochecks (buffer, 0, buffer.Length, flags, remote_end);
  1218. }
  1219. public int SendTo (byte [] buffer, int size, SocketFlags flags, EndPoint remote_end)
  1220. {
  1221. if (buffer == null)
  1222. throw new ArgumentNullException ("buffer");
  1223. if (remote_end == null)
  1224. throw new ArgumentNullException ("remote_end");
  1225. if (size < 0 || size > buffer.Length)
  1226. throw new ArgumentOutOfRangeException ("size");
  1227. return SendTo_nochecks (buffer, 0, size, flags, remote_end);
  1228. }
  1229. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1230. private extern static int SendTo_internal(IntPtr sock,
  1231. byte[] buffer,
  1232. int offset,
  1233. int count,
  1234. SocketFlags flags,
  1235. SocketAddress sa,
  1236. out int error);
  1237. public int SendTo (byte [] buffer, int offset, int size, SocketFlags flags,
  1238. EndPoint remote_end)
  1239. {
  1240. if (buffer == null)
  1241. throw new ArgumentNullException ("buffer");
  1242. if (remote_end == null)
  1243. throw new ArgumentNullException("remote_end");
  1244. if (offset < 0 || offset > buffer.Length)
  1245. throw new ArgumentOutOfRangeException ("offset");
  1246. if (size < 0 || offset + size > buffer.Length)
  1247. throw new ArgumentOutOfRangeException ("size");
  1248. return SendTo_nochecks (buffer, offset, size, flags, remote_end);
  1249. }
  1250. int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags,
  1251. EndPoint remote_end)
  1252. {
  1253. SocketAddress sockaddr = remote_end.Serialize ();
  1254. int ret, error;
  1255. ret = SendTo_internal (socket, buffer, offset, size, flags, sockaddr, out error);
  1256. if (error != 0) {
  1257. if (error != 10035 && error != 10036) // WSAEWOULDBLOCK && WSAEINPROGRESS
  1258. connected = false;
  1259. throw new SocketException (error);
  1260. }
  1261. connected = true;
  1262. return ret;
  1263. }
  1264. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1265. private extern static void SetSocketOption_internal (IntPtr socket, SocketOptionLevel level,
  1266. SocketOptionName name, object obj_val,
  1267. byte [] byte_val, int int_val,
  1268. out int error);
  1269. public void SetSocketOption(SocketOptionLevel level,
  1270. SocketOptionName name,
  1271. byte[] opt_value) {
  1272. int error;
  1273. SetSocketOption_internal(socket, level, name, null,
  1274. opt_value, 0, out error);
  1275. if (error != 0) {
  1276. throw new SocketException (error);
  1277. }
  1278. }
  1279. public void SetSocketOption(SocketOptionLevel level,
  1280. SocketOptionName name,
  1281. int opt_value) {
  1282. int error;
  1283. SetSocketOption_internal(socket, level, name, null,
  1284. null, opt_value, out error);
  1285. if (error != 0) {
  1286. throw new SocketException (error);
  1287. }
  1288. }
  1289. public void SetSocketOption(SocketOptionLevel level,
  1290. SocketOptionName name,
  1291. object opt_value) {
  1292. if(opt_value==null) {
  1293. throw new ArgumentNullException();
  1294. }
  1295. int error;
  1296. /* Passing a bool as the third parameter to
  1297. * SetSocketOption causes this overload to be
  1298. * used when in fact we want to pass the value
  1299. * to the runtime as an int.
  1300. */
  1301. if (opt_value is System.Boolean) {
  1302. bool bool_val = (bool) opt_value;
  1303. int int_val = (bool_val) ? 1 : 0;
  1304. SetSocketOption_internal (socket, level, name, null, null, int_val, out error);
  1305. } else {
  1306. SetSocketOption_internal (socket, level, name, opt_value, null, 0, out error);
  1307. }
  1308. if (error != 0) {
  1309. throw new SocketException (error);
  1310. }
  1311. }
  1312. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1313. private extern static void Shutdown_internal(IntPtr socket, SocketShutdown how, out int error);
  1314. public void Shutdown(SocketShutdown how) {
  1315. int error;
  1316. Shutdown_internal(socket, how, out error);
  1317. if (error != 0) {
  1318. throw new SocketException (error);
  1319. }
  1320. }
  1321. public override int GetHashCode ()
  1322. {
  1323. return (int) socket;
  1324. }
  1325. private bool disposed;
  1326. protected virtual void Dispose(bool explicitDisposing) {
  1327. if (!disposed) {
  1328. int error;
  1329. disposed = true;
  1330. connected = false;
  1331. if (!explicitDisposing) {
  1332. closed = true;
  1333. Close_internal (socket, out error);
  1334. if (error != 0) {
  1335. throw new SocketException (error);
  1336. }
  1337. return;
  1338. }
  1339. if (Interlocked.CompareExchange (ref pendingEnds, 0, 0) == 0) {
  1340. closed = true;
  1341. Close_internal (socket, out error);
  1342. if (error != 0) {
  1343. throw new SocketException (error);
  1344. }
  1345. } else {
  1346. Interlocked.CompareExchange (ref closeDelayed, 1, 0);
  1347. }
  1348. }
  1349. }
  1350. void IDisposable.Dispose ()
  1351. {
  1352. Dispose (true);
  1353. GC.SuppressFinalize (this);
  1354. }
  1355. ~Socket () {
  1356. Dispose(false);
  1357. }
  1358. static Hashtable asyncObjects;
  1359. static void KeepReference (object o)
  1360. {
  1361. lock (typeof (Socket)) {
  1362. if (asyncObjects == null)
  1363. asyncObjects = new Hashtable ();
  1364. asyncObjects [o] = o;
  1365. }
  1366. }
  1367. static void RemoveReference (object o)
  1368. {
  1369. lock (typeof (Socket)) {
  1370. if (asyncObjects == null)
  1371. return;
  1372. asyncObjects.Remove (o);
  1373. }
  1374. }
  1375. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1376. extern static bool GetSupportsAsync ();
  1377. static bool FakeGetSupportsAsync ()
  1378. {
  1379. if (Environment.GetEnvironmentVariable ("MONO_ENABLE_SOCKET_AIO") != null)
  1380. return GetSupportsAsync ();
  1381. return false;
  1382. }
  1383. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1384. extern static void AsyncReceiveInternal (SocketAsyncResult ares, out int error);
  1385. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1386. extern static void AsyncSendInternal (SocketAsyncResult ares, out int error);
  1387. }
  1388. }