Socket.cs 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699
  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. if(read_list!=null) {
  361. read_list.Clear();
  362. for(i=0; i<read_arr.Length; i++) {
  363. read_list.Add(read_arr[i]);
  364. }
  365. }
  366. if(write_list!=null) {
  367. write_list.Clear();
  368. for(i=0; i<write_arr.Length; i++) {
  369. write_list.Add(write_arr[i]);
  370. }
  371. }
  372. if(err_list!=null) {
  373. err_list.Clear();
  374. for(i=0; i<err_arr.Length; i++) {
  375. err_list.Add(err_arr[i]);
  376. }
  377. }
  378. }
  379. static Socket() {
  380. Assembly ass;
  381. try {
  382. ass = Assembly.Load (Consts.AssemblyMono_Posix);
  383. } catch (FileNotFoundException) {
  384. return;
  385. }
  386. unixendpointtype=ass.GetType("Mono.Posix.UnixEndPoint");
  387. /* The endpoint Create() method is an instance
  388. * method :-(
  389. */
  390. Type[] arg_types=new Type[1];
  391. arg_types[0]=typeof(string);
  392. ConstructorInfo cons=unixendpointtype.GetConstructor(arg_types);
  393. object[] args=new object[1];
  394. args[0]="";
  395. unixendpoint=cons.Invoke(args);
  396. }
  397. // private constructor used by Accept, which already
  398. // has a socket handle to use
  399. private Socket(AddressFamily family, SocketType type,
  400. ProtocolType proto, IntPtr sock) {
  401. address_family=family;
  402. socket_type=type;
  403. protocol_type=proto;
  404. socket=sock;
  405. connected=true;
  406. }
  407. // Creates a new system socket, returning the handle
  408. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  409. private extern IntPtr Socket_internal(AddressFamily family,
  410. SocketType type,
  411. ProtocolType proto,
  412. out int error);
  413. public Socket(AddressFamily family, SocketType type,
  414. ProtocolType proto) {
  415. address_family=family;
  416. socket_type=type;
  417. protocol_type=proto;
  418. int error;
  419. socket=Socket_internal(family, type, proto, out error);
  420. if (error != 0) {
  421. throw new SocketException (error);
  422. }
  423. }
  424. public AddressFamily AddressFamily {
  425. get {
  426. return(address_family);
  427. }
  428. }
  429. // Returns the amount of data waiting to be read on socket
  430. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  431. private extern static int Available_internal(IntPtr socket,
  432. out int error);
  433. public int Available {
  434. get {
  435. if (disposed && closed)
  436. throw new ObjectDisposedException (GetType ().ToString ());
  437. int ret, error;
  438. ret = Available_internal(socket, out error);
  439. if (error != 0) {
  440. throw new SocketException (error);
  441. }
  442. return(ret);
  443. }
  444. }
  445. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  446. private extern static void Blocking_internal(IntPtr socket,
  447. bool block,
  448. out int error);
  449. public bool Blocking {
  450. get {
  451. return(blocking);
  452. }
  453. set {
  454. int error;
  455. Blocking_internal(socket, value, out error);
  456. if (error != 0) {
  457. throw new SocketException (error);
  458. }
  459. blocking=value;
  460. }
  461. }
  462. public bool Connected {
  463. get {
  464. return(connected);
  465. }
  466. }
  467. public IntPtr Handle {
  468. get {
  469. return(socket);
  470. }
  471. }
  472. // Returns the local endpoint details in addr and port
  473. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  474. private extern static SocketAddress LocalEndPoint_internal(IntPtr socket, out int error);
  475. [MonoTODO("Support non-IP endpoints")]
  476. public EndPoint LocalEndPoint {
  477. get {
  478. if (disposed && closed)
  479. throw new ObjectDisposedException (GetType ().ToString ());
  480. SocketAddress sa;
  481. int error;
  482. sa=LocalEndPoint_internal(socket, out error);
  483. if (error != 0) {
  484. throw new SocketException (error);
  485. }
  486. if(sa.Family==AddressFamily.InterNetwork || sa.Family==AddressFamily.InterNetworkV6) {
  487. // Stupidly, EndPoint.Create() is an
  488. // instance method
  489. return new IPEndPoint(0, 0).Create(sa);
  490. } else if (sa.Family==AddressFamily.Unix &&
  491. unixendpoint!=null) {
  492. return((EndPoint)unixendpointtype.InvokeMember("Create", BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public, null, unixendpoint, new object[] {sa}));
  493. } else {
  494. throw new NotImplementedException();
  495. }
  496. }
  497. }
  498. public ProtocolType ProtocolType {
  499. get {
  500. return(protocol_type);
  501. }
  502. }
  503. // Returns the remote endpoint details in addr and port
  504. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  505. private extern static SocketAddress RemoteEndPoint_internal(IntPtr socket, out int error);
  506. [MonoTODO("Support non-IP endpoints")]
  507. public EndPoint RemoteEndPoint {
  508. get {
  509. if (disposed && closed)
  510. throw new ObjectDisposedException (GetType ().ToString ());
  511. SocketAddress sa;
  512. int error;
  513. sa=RemoteEndPoint_internal(socket, out error);
  514. if (error != 0) {
  515. throw new SocketException (error);
  516. }
  517. if(sa.Family==AddressFamily.InterNetwork || sa.Family==AddressFamily.InterNetworkV6 ) {
  518. // Stupidly, EndPoint.Create() is an
  519. // instance method
  520. return new IPEndPoint(0, 0).Create(sa);
  521. } else if (sa.Family==AddressFamily.Unix &&
  522. unixendpoint!=null) {
  523. return((EndPoint)unixendpointtype.InvokeMember("Create", BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public, null, unixendpoint, new object[] {sa}));
  524. } else {
  525. throw new NotImplementedException();
  526. }
  527. }
  528. }
  529. public SocketType SocketType {
  530. get {
  531. return(socket_type);
  532. }
  533. }
  534. #if NET_1_1
  535. public static bool SupportsIPv4 {
  536. get {
  537. CheckProtocolSupport();
  538. return ipv4Supported == 1;
  539. }
  540. }
  541. public static bool SupportsIPv6 {
  542. get {
  543. CheckProtocolSupport();
  544. return ipv6Supported == 1;
  545. }
  546. }
  547. #else
  548. internal static bool SupportsIPv4
  549. {
  550. get
  551. {
  552. return true;
  553. }
  554. }
  555. internal static bool SupportsIPv6
  556. {
  557. get
  558. {
  559. return false;
  560. }
  561. }
  562. #endif
  563. internal static void CheckProtocolSupport()
  564. {
  565. if(ipv4Supported == -1) {
  566. try {
  567. Socket tmp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  568. tmp.Close();
  569. ipv4Supported = 1;
  570. }
  571. catch {
  572. ipv4Supported = 0;
  573. }
  574. }
  575. if(ipv6Supported == -1) {
  576. NetConfig config = (NetConfig)System.Configuration.ConfigurationSettings.GetConfig("system.net/settings");
  577. if(config != null)
  578. ipv6Supported = config.ipv6Enabled?-1:0;
  579. if(ipv6Supported != 0) {
  580. try {
  581. Socket tmp = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
  582. tmp.Close();
  583. ipv6Supported = 1;
  584. }
  585. catch { }
  586. }
  587. }
  588. }
  589. // Creates a new system socket, returning the handle
  590. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  591. private extern static IntPtr Accept_internal(IntPtr sock,
  592. out int error);
  593. public Socket Accept() {
  594. if (disposed && closed)
  595. throw new ObjectDisposedException (GetType ().ToString ());
  596. int error;
  597. IntPtr sock=Accept_internal(socket, out error);
  598. if (!blocking && error == 10035) {
  599. Poll (-1, SelectMode.SelectRead);
  600. sock = Accept_internal (socket, out error);
  601. }
  602. if (error != 0) {
  603. throw new SocketException (error);
  604. }
  605. return(new Socket(this.AddressFamily, this.SocketType,
  606. this.ProtocolType, sock));
  607. }
  608. public IAsyncResult BeginAccept(AsyncCallback callback,
  609. object state) {
  610. if (disposed && closed)
  611. throw new ObjectDisposedException (GetType ().ToString ());
  612. Interlocked.Increment (ref pendingEnds);
  613. SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
  614. Worker worker = new Worker (req);
  615. SocketAsyncCall sac = new SocketAsyncCall (worker.Accept);
  616. sac.BeginInvoke (null, null);
  617. return(req);
  618. }
  619. public IAsyncResult BeginConnect(EndPoint end_point,
  620. AsyncCallback callback,
  621. object state) {
  622. if (disposed && closed)
  623. throw new ObjectDisposedException (GetType ().ToString ());
  624. if (end_point == null)
  625. throw new ArgumentNullException ("end_point");
  626. Interlocked.Increment (ref pendingEnds);
  627. SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
  628. req.EndPoint = end_point;
  629. Worker worker = new Worker (req);
  630. SocketAsyncCall sac = new SocketAsyncCall (worker.Connect);
  631. sac.BeginInvoke (null, null);
  632. return(req);
  633. }
  634. public IAsyncResult BeginReceive(byte[] buffer, int offset,
  635. int size,
  636. SocketFlags socket_flags,
  637. AsyncCallback callback,
  638. object state) {
  639. if (disposed && closed)
  640. throw new ObjectDisposedException (GetType ().ToString ());
  641. if (buffer == null)
  642. throw new ArgumentNullException ("buffer");
  643. if (offset < 0 || offset > buffer.Length)
  644. throw new ArgumentOutOfRangeException ("offset");
  645. if (size < 0 || offset + size > buffer.Length)
  646. throw new ArgumentOutOfRangeException ("size");
  647. Interlocked.Increment (ref pendingEnds);
  648. SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
  649. req.Buffer = buffer;
  650. req.Offset = offset;
  651. req.Size = size;
  652. req.SockFlags = socket_flags;
  653. if (supportsAsync && socket_type == SocketType.Stream) {
  654. int error;
  655. req.CreateAsyncDelegate ();
  656. KeepReference (req);
  657. AsyncReceiveInternal (req, out error);
  658. if (error != 0 && error != 10036) // WSAEINPROGRESS
  659. throw new SocketException (error);
  660. } else {
  661. Worker worker = new Worker (req);
  662. SocketAsyncCall sac = new SocketAsyncCall (worker.Receive);
  663. sac.BeginInvoke (null, null);
  664. }
  665. return req;
  666. }
  667. public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset,
  668. int size,
  669. SocketFlags socket_flags,
  670. ref EndPoint remote_end,
  671. AsyncCallback callback,
  672. object state) {
  673. if (disposed && closed)
  674. throw new ObjectDisposedException (GetType ().ToString ());
  675. if (buffer == null)
  676. throw new ArgumentNullException ("buffer");
  677. if (offset < 0)
  678. throw new ArgumentOutOfRangeException ("offset must be >= 0");
  679. if (size < 0)
  680. throw new ArgumentOutOfRangeException ("size must be >= 0");
  681. if (offset + size > buffer.Length)
  682. throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
  683. Interlocked.Increment (ref pendingEnds);
  684. SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
  685. req.Buffer = buffer;
  686. req.Offset = offset;
  687. req.Size = size;
  688. req.SockFlags = socket_flags;
  689. req.EndPoint = remote_end;
  690. Worker worker = new Worker (req);
  691. SocketAsyncCall sac = new SocketAsyncCall (worker.ReceiveFrom);
  692. sac.BeginInvoke (null, null);
  693. return req;
  694. }
  695. public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socket_flags,
  696. AsyncCallback callback, object state)
  697. {
  698. if (disposed && closed)
  699. throw new ObjectDisposedException (GetType ().ToString ());
  700. if (buffer == null)
  701. throw new ArgumentNullException ("buffer");
  702. if (offset < 0)
  703. throw new ArgumentOutOfRangeException ("offset must be >= 0");
  704. if (size < 0)
  705. throw new ArgumentOutOfRangeException ("size must be >= 0");
  706. if (offset + size > buffer.Length)
  707. throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
  708. Interlocked.Increment (ref pendingEnds);
  709. SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
  710. req.Buffer = buffer;
  711. req.Offset = offset;
  712. req.Size = size;
  713. req.SockFlags = socket_flags;
  714. if (supportsAsync && socket_type == SocketType.Stream) {
  715. int error;
  716. req.CreateAsyncDelegate ();
  717. KeepReference (req);
  718. AsyncSendInternal (req, out error);
  719. if (error != 0 && error != 10036) // WSAEINPROGRESS
  720. throw new SocketException (error);
  721. } else {
  722. Worker worker = new Worker (req);
  723. SocketAsyncCall sac = new SocketAsyncCall (worker.Send);
  724. sac.BeginInvoke (null, null);
  725. }
  726. return req;
  727. }
  728. public IAsyncResult BeginSendTo(byte[] buffer, int offset,
  729. int size,
  730. SocketFlags socket_flags,
  731. EndPoint remote_end,
  732. AsyncCallback callback,
  733. object state) {
  734. if (disposed && closed)
  735. throw new ObjectDisposedException (GetType ().ToString ());
  736. if (buffer == null)
  737. throw new ArgumentNullException ("buffer");
  738. if (offset < 0)
  739. throw new ArgumentOutOfRangeException ("offset must be >= 0");
  740. if (size < 0)
  741. throw new ArgumentOutOfRangeException ("size must be >= 0");
  742. if (offset + size > buffer.Length)
  743. throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
  744. Interlocked.Increment (ref pendingEnds);
  745. SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
  746. req.Buffer = buffer;
  747. req.Offset = offset;
  748. req.Size = size;
  749. req.SockFlags = socket_flags;
  750. req.EndPoint = remote_end;
  751. Worker worker = new Worker(req);
  752. SocketAsyncCall sac = new SocketAsyncCall (worker.SendTo);
  753. sac.BeginInvoke (null, null);
  754. return req;
  755. }
  756. // Creates a new system socket, returning the handle
  757. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  758. private extern static void Bind_internal(IntPtr sock,
  759. SocketAddress sa,
  760. out int error);
  761. public void Bind(EndPoint local_end) {
  762. if (disposed && closed)
  763. throw new ObjectDisposedException (GetType ().ToString ());
  764. if(local_end==null) {
  765. throw new ArgumentNullException("local_end");
  766. }
  767. int error;
  768. Bind_internal(socket, local_end.Serialize(),
  769. out error);
  770. if (error != 0) {
  771. throw new SocketException (error);
  772. }
  773. }
  774. // Closes the socket
  775. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  776. private extern static void Close_internal(IntPtr socket,
  777. out int error);
  778. public void Close() {
  779. ((IDisposable) this).Dispose ();
  780. }
  781. // Connects to the remote address
  782. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  783. private extern static void Connect_internal(IntPtr sock,
  784. SocketAddress sa,
  785. out int error);
  786. public void Connect(EndPoint remote_end) {
  787. if (disposed && closed)
  788. throw new ObjectDisposedException (GetType ().ToString ());
  789. if(remote_end==null) {
  790. throw new ArgumentNullException("remote_end");
  791. }
  792. int error;
  793. SocketAddress serial = remote_end.Serialize ();
  794. Connect_internal(socket, serial, out error);
  795. if (!blocking && error == 10035) {
  796. Poll (-1, SelectMode.SelectWrite);
  797. Connect_internal (socket, serial, out error);
  798. }
  799. if (error != 0)
  800. throw new SocketException (error);
  801. connected=true;
  802. }
  803. public Socket EndAccept(IAsyncResult result) {
  804. if (disposed && closed)
  805. throw new ObjectDisposedException (GetType ().ToString ());
  806. if (result == null)
  807. throw new ArgumentNullException ("result");
  808. SocketAsyncResult req = result as SocketAsyncResult;
  809. if (req == null)
  810. throw new ArgumentException ("Invalid IAsyncResult", "result");
  811. if (!result.IsCompleted)
  812. result.AsyncWaitHandle.WaitOne();
  813. Interlocked.Decrement (ref pendingEnds);
  814. CheckIfClose ();
  815. req.CheckIfThrowDelayedException();
  816. return req.Socket;
  817. }
  818. public void EndConnect(IAsyncResult result) {
  819. if (disposed && closed)
  820. throw new ObjectDisposedException (GetType ().ToString ());
  821. if (result == null)
  822. throw new ArgumentNullException ("result");
  823. SocketAsyncResult req = result as SocketAsyncResult;
  824. if (req == null)
  825. throw new ArgumentException ("Invalid IAsyncResult", "result");
  826. if (!result.IsCompleted)
  827. result.AsyncWaitHandle.WaitOne();
  828. Interlocked.Decrement (ref pendingEnds);
  829. CheckIfClose ();
  830. req.CheckIfThrowDelayedException();
  831. }
  832. public int EndReceive(IAsyncResult result) {
  833. if (disposed && closed)
  834. throw new ObjectDisposedException (GetType ().ToString ());
  835. if (result == null)
  836. throw new ArgumentNullException ("result");
  837. SocketAsyncResult req = result as SocketAsyncResult;
  838. if (req == null)
  839. throw new ArgumentException ("Invalid IAsyncResult", "result");
  840. if (supportsAsync && socket_type == SocketType.Stream)
  841. RemoveReference (req);
  842. if (!result.IsCompleted)
  843. result.AsyncWaitHandle.WaitOne();
  844. Interlocked.Decrement (ref pendingEnds);
  845. CheckIfClose ();
  846. req.CheckIfThrowDelayedException();
  847. return req.Total;
  848. }
  849. public int EndReceiveFrom(IAsyncResult result,
  850. ref EndPoint end_point) {
  851. if (disposed && closed)
  852. throw new ObjectDisposedException (GetType ().ToString ());
  853. if (result == null)
  854. throw new ArgumentNullException ("result");
  855. SocketAsyncResult req = result as SocketAsyncResult;
  856. if (req == null)
  857. throw new ArgumentException ("Invalid IAsyncResult", "result");
  858. if (!result.IsCompleted)
  859. result.AsyncWaitHandle.WaitOne();
  860. Interlocked.Decrement (ref pendingEnds);
  861. CheckIfClose ();
  862. req.CheckIfThrowDelayedException();
  863. end_point = req.EndPoint;
  864. return req.Total;
  865. }
  866. public int EndSend(IAsyncResult result) {
  867. if (disposed && closed)
  868. throw new ObjectDisposedException (GetType ().ToString ());
  869. if (result == null)
  870. throw new ArgumentNullException ("result");
  871. SocketAsyncResult req = result as SocketAsyncResult;
  872. if (req == null)
  873. throw new ArgumentException ("Invalid IAsyncResult", "result");
  874. if (supportsAsync && socket_type == SocketType.Stream)
  875. RemoveReference (req);
  876. if (!result.IsCompleted)
  877. result.AsyncWaitHandle.WaitOne();
  878. Interlocked.Decrement (ref pendingEnds);
  879. CheckIfClose ();
  880. req.CheckIfThrowDelayedException();
  881. return req.Total;
  882. }
  883. public int EndSendTo(IAsyncResult result) {
  884. if (disposed && closed)
  885. throw new ObjectDisposedException (GetType ().ToString ());
  886. if (result == null)
  887. throw new ArgumentNullException ("result");
  888. SocketAsyncResult req = result as SocketAsyncResult;
  889. if (req == null)
  890. throw new ArgumentException ("Invalid IAsyncResult", "result");
  891. if (!result.IsCompleted)
  892. result.AsyncWaitHandle.WaitOne();
  893. Interlocked.Decrement (ref pendingEnds);
  894. CheckIfClose ();
  895. req.CheckIfThrowDelayedException();
  896. return req.Total;
  897. }
  898. void CheckIfClose ()
  899. {
  900. if (Interlocked.CompareExchange (ref closeDelayed, 0, 1) == 1 &&
  901. Interlocked.CompareExchange (ref pendingEnds, 0, 0) == 0) {
  902. closed = true;
  903. int error;
  904. Close_internal(socket, out error);
  905. if (error != 0) {
  906. throw new SocketException (error);
  907. }
  908. }
  909. }
  910. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  911. private extern static void GetSocketOption_obj_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, out object obj_val, out int error);
  912. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  913. private extern static void GetSocketOption_arr_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val, out int error);
  914. public object GetSocketOption(SocketOptionLevel level,
  915. SocketOptionName name) {
  916. object obj_val;
  917. int error;
  918. GetSocketOption_obj_internal(socket, level, name,
  919. out obj_val, out error);
  920. if (error != 0) {
  921. throw new SocketException (error);
  922. }
  923. if(name==SocketOptionName.Linger) {
  924. return((LingerOption)obj_val);
  925. } else if (name==SocketOptionName.AddMembership ||
  926. name==SocketOptionName.DropMembership) {
  927. return((MulticastOption)obj_val);
  928. } else if (obj_val is int) {
  929. return((int)obj_val);
  930. } else {
  931. return(obj_val);
  932. }
  933. }
  934. public void GetSocketOption(SocketOptionLevel level,
  935. SocketOptionName name,
  936. byte[] opt_value) {
  937. int opt_value_len=opt_value.Length;
  938. int error;
  939. GetSocketOption_arr_internal(socket, level, name,
  940. ref opt_value, out error);
  941. if (error != 0) {
  942. throw new SocketException (error);
  943. }
  944. }
  945. public byte[] GetSocketOption(SocketOptionLevel level,
  946. SocketOptionName name,
  947. int length) {
  948. byte[] byte_val=new byte[length];
  949. int error;
  950. GetSocketOption_arr_internal(socket, level, name,
  951. ref byte_val, out error);
  952. if (error != 0) {
  953. throw new SocketException (error);
  954. }
  955. return(byte_val);
  956. }
  957. // See Socket.IOControl, WSAIoctl documentation in MSDN. The
  958. // common options between UNIX and Winsock are FIONREAD,
  959. // FIONBIO and SIOCATMARK. Anything else will depend on the
  960. // system.
  961. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  962. extern static int WSAIoctl (IntPtr sock, int ioctl_code,
  963. byte [] input, byte [] output,
  964. out int error);
  965. public int IOControl (int ioctl_code, byte [] in_value, byte [] out_value)
  966. {
  967. if (disposed)
  968. throw new ObjectDisposedException (GetType ().ToString ());
  969. int error;
  970. int result = WSAIoctl (socket, ioctl_code, in_value,
  971. out_value, out error);
  972. if (error != 0) {
  973. throw new SocketException (error);
  974. }
  975. if (result == -1)
  976. throw new InvalidOperationException ("Must use Blocking property instead.");
  977. return result;
  978. }
  979. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  980. private extern static void Listen_internal(IntPtr sock,
  981. int backlog,
  982. out int error);
  983. public void Listen(int backlog) {
  984. int error;
  985. Listen_internal(socket, backlog, out error);
  986. if (error != 0) {
  987. throw new SocketException (error);
  988. }
  989. }
  990. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  991. extern static bool Poll_internal (IntPtr socket, SelectMode mode, int timeout, out int error);
  992. public bool Poll (int time_us, SelectMode mode)
  993. {
  994. if (mode != SelectMode.SelectRead &&
  995. mode != SelectMode.SelectWrite &&
  996. mode != SelectMode.SelectError)
  997. throw new NotSupportedException ("'mode' parameter is not valid.");
  998. int error;
  999. bool result = Poll_internal (socket, mode, time_us, out error);
  1000. if (error != 0)
  1001. throw new SocketException (error);
  1002. return result;
  1003. }
  1004. public int Receive (byte [] buf)
  1005. {
  1006. if (buf == null)
  1007. throw new ArgumentNullException ("buf");
  1008. return Receive_nochecks (buf, 0, buf.Length, SocketFlags.None);
  1009. }
  1010. public int Receive (byte [] buf, SocketFlags flags)
  1011. {
  1012. if (buf == null)
  1013. throw new ArgumentNullException ("buf");
  1014. return Receive_nochecks (buf, 0, buf.Length, flags);
  1015. }
  1016. public int Receive (byte [] buf, int size, SocketFlags flags)
  1017. {
  1018. if (buf == null)
  1019. throw new ArgumentNullException ("buf");
  1020. if (size < 0 || size > buf.Length)
  1021. throw new ArgumentOutOfRangeException ("size");
  1022. return Receive_nochecks (buf, 0, size, flags);
  1023. }
  1024. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1025. private extern static int Receive_internal(IntPtr sock,
  1026. byte[] buffer,
  1027. int offset,
  1028. int count,
  1029. SocketFlags flags,
  1030. out int error);
  1031. public int Receive (byte [] buf, int offset, int size, SocketFlags flags)
  1032. {
  1033. if (buf == null)
  1034. throw new ArgumentNullException ("buf");
  1035. if (offset < 0 || offset > buf.Length)
  1036. throw new ArgumentOutOfRangeException ("offset");
  1037. if (size < 0 || offset + size > buf.Length)
  1038. throw new ArgumentOutOfRangeException ("size");
  1039. return Receive_nochecks (buf, offset, size, flags);
  1040. }
  1041. int Receive_nochecks (byte [] buf, int offset, int size, SocketFlags flags)
  1042. {
  1043. int ret, error;
  1044. ret = Receive_internal (socket, buf, offset, size, flags, out error);
  1045. if (error != 0) {
  1046. connected = false;
  1047. throw new SocketException (error);
  1048. }
  1049. connected = true;
  1050. return ret;
  1051. }
  1052. public int ReceiveFrom (byte [] buf, ref EndPoint remote_end)
  1053. {
  1054. if (buf == null)
  1055. throw new ArgumentNullException ("buf");
  1056. if (remote_end == null)
  1057. throw new ArgumentNullException ("remote_end");
  1058. return ReceiveFrom_nochecks (buf, 0, buf.Length, SocketFlags.None, ref remote_end);
  1059. }
  1060. public int ReceiveFrom (byte [] buf, SocketFlags flags, ref EndPoint remote_end)
  1061. {
  1062. if (buf == null)
  1063. throw new ArgumentNullException ("buf");
  1064. if (remote_end == null)
  1065. throw new ArgumentNullException ("remote_end");
  1066. return ReceiveFrom_nochecks (buf, 0, buf.Length, flags, ref remote_end);
  1067. }
  1068. public int ReceiveFrom (byte [] buf, int size, SocketFlags flags,
  1069. ref EndPoint remote_end)
  1070. {
  1071. if (buf == null)
  1072. throw new ArgumentNullException ("buf");
  1073. if (remote_end == null)
  1074. throw new ArgumentNullException ("remote_end");
  1075. if (size < 0 || size > buf.Length)
  1076. throw new ArgumentOutOfRangeException ("size");
  1077. return ReceiveFrom_nochecks (buf, 0, size, flags, ref remote_end);
  1078. }
  1079. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1080. private extern static int RecvFrom_internal(IntPtr sock,
  1081. byte[] buffer,
  1082. int offset,
  1083. int count,
  1084. SocketFlags flags,
  1085. ref SocketAddress sockaddr,
  1086. out int error);
  1087. public int ReceiveFrom (byte [] buf, int offset, int size, SocketFlags flags,
  1088. ref EndPoint remote_end)
  1089. {
  1090. if (buf == null)
  1091. throw new ArgumentNullException ("buf");
  1092. if (remote_end == null)
  1093. throw new ArgumentNullException ("remote_end");
  1094. if (offset < 0 || offset > buf.Length)
  1095. throw new ArgumentOutOfRangeException ("offset");
  1096. if (size < 0 || offset + size > buf.Length)
  1097. throw new ArgumentOutOfRangeException ("size");
  1098. return ReceiveFrom_nochecks (buf, offset, size, flags, ref remote_end);
  1099. }
  1100. int ReceiveFrom_nochecks (byte [] buf, int offset, int size, SocketFlags flags,
  1101. ref EndPoint remote_end)
  1102. {
  1103. SocketAddress sockaddr = remote_end.Serialize();
  1104. int cnt, error;
  1105. cnt = RecvFrom_internal (socket, buf, offset, size, flags, ref sockaddr, out error);
  1106. if (error != 0) {
  1107. connected = false;
  1108. throw new SocketException (error);
  1109. }
  1110. connected = true;
  1111. // Stupidly, EndPoint.Create() is an
  1112. // instance method
  1113. remote_end = remote_end.Create (sockaddr);
  1114. return cnt;
  1115. }
  1116. public int Send (byte [] buf)
  1117. {
  1118. if (buf == null)
  1119. throw new ArgumentNullException ("buf");
  1120. return Send_nochecks (buf, 0, buf.Length, SocketFlags.None);
  1121. }
  1122. public int Send (byte [] buf, SocketFlags flags)
  1123. {
  1124. if (buf == null)
  1125. throw new ArgumentNullException ("buf");
  1126. return Send_nochecks (buf, 0, buf.Length, flags);
  1127. }
  1128. public int Send (byte [] buf, int size, SocketFlags flags)
  1129. {
  1130. if (buf == null)
  1131. throw new ArgumentNullException ("buf");
  1132. if (size < 0 || size > buf.Length)
  1133. throw new ArgumentOutOfRangeException ("size");
  1134. return Send_nochecks (buf, 0, size, flags);
  1135. }
  1136. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1137. private extern static int Send_internal(IntPtr sock,
  1138. byte[] buf, int offset,
  1139. int count,
  1140. SocketFlags flags,
  1141. out int error);
  1142. public int Send (byte [] buf, int offset, int size, SocketFlags flags)
  1143. {
  1144. if (buf == null)
  1145. throw new ArgumentNullException ("buffer");
  1146. if (offset < 0 || offset > buf.Length)
  1147. throw new ArgumentOutOfRangeException ("offset");
  1148. if (size < 0 || offset + size > buf.Length)
  1149. throw new ArgumentOutOfRangeException ("size");
  1150. return Send_nochecks (buf, offset, size, flags);
  1151. }
  1152. int Send_nochecks (byte [] buf, int offset, int size, SocketFlags flags)
  1153. {
  1154. if (size == 0)
  1155. return 0;
  1156. int ret, error;
  1157. ret = Send_internal (socket, buf, offset, size, flags, out error);
  1158. if (error != 0) {
  1159. connected = false;
  1160. throw new SocketException (error);
  1161. }
  1162. connected = true;
  1163. return ret;
  1164. }
  1165. public int SendTo (byte [] buffer, EndPoint remote_end)
  1166. {
  1167. if (buffer == null)
  1168. throw new ArgumentNullException ("buffer");
  1169. if (remote_end == null)
  1170. throw new ArgumentNullException ("remote_end");
  1171. return SendTo_nochecks (buffer, 0, buffer.Length, SocketFlags.None, remote_end);
  1172. }
  1173. public int SendTo (byte [] buffer, SocketFlags flags, EndPoint remote_end)
  1174. {
  1175. if (buffer == null)
  1176. throw new ArgumentNullException ("buffer");
  1177. if (remote_end == null)
  1178. throw new ArgumentNullException ("remote_end");
  1179. return SendTo_nochecks (buffer, 0, buffer.Length, flags, remote_end);
  1180. }
  1181. public int SendTo (byte [] buffer, int size, SocketFlags flags, EndPoint remote_end)
  1182. {
  1183. if (buffer == null)
  1184. throw new ArgumentNullException ("buffer");
  1185. if (remote_end == null)
  1186. throw new ArgumentNullException ("remote_end");
  1187. if (size < 0 || size > buffer.Length)
  1188. throw new ArgumentOutOfRangeException ("size");
  1189. return SendTo_nochecks (buffer, 0, size, flags, remote_end);
  1190. }
  1191. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1192. private extern static int SendTo_internal(IntPtr sock,
  1193. byte[] buffer,
  1194. int offset,
  1195. int count,
  1196. SocketFlags flags,
  1197. SocketAddress sa,
  1198. out int error);
  1199. public int SendTo (byte [] buffer, int offset, int size, SocketFlags flags,
  1200. EndPoint remote_end)
  1201. {
  1202. if (buffer == null)
  1203. throw new ArgumentNullException ("buffer");
  1204. if (remote_end == null)
  1205. throw new ArgumentNullException("remote_end");
  1206. if (offset < 0 || offset > buffer.Length)
  1207. throw new ArgumentOutOfRangeException ("offset");
  1208. if (size < 0 || offset + size > buffer.Length)
  1209. throw new ArgumentOutOfRangeException ("size");
  1210. return SendTo_nochecks (buffer, offset, size, flags, remote_end);
  1211. }
  1212. int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags,
  1213. EndPoint remote_end)
  1214. {
  1215. SocketAddress sockaddr = remote_end.Serialize ();
  1216. int ret, error;
  1217. ret = SendTo_internal (socket, buffer, offset, size, flags, sockaddr, out error);
  1218. if (error != 0) {
  1219. connected = false;
  1220. throw new SocketException (error);
  1221. }
  1222. connected = true;
  1223. return ret;
  1224. }
  1225. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1226. private extern static void SetSocketOption_internal (IntPtr socket, SocketOptionLevel level,
  1227. SocketOptionName name, object obj_val,
  1228. byte [] byte_val, int int_val,
  1229. out int error);
  1230. public void SetSocketOption(SocketOptionLevel level,
  1231. SocketOptionName name,
  1232. byte[] opt_value) {
  1233. int error;
  1234. SetSocketOption_internal(socket, level, name, null,
  1235. opt_value, 0, out error);
  1236. if (error != 0) {
  1237. throw new SocketException (error);
  1238. }
  1239. }
  1240. public void SetSocketOption(SocketOptionLevel level,
  1241. SocketOptionName name,
  1242. int opt_value) {
  1243. int error;
  1244. SetSocketOption_internal(socket, level, name, null,
  1245. null, opt_value, out error);
  1246. if (error != 0) {
  1247. throw new SocketException (error);
  1248. }
  1249. }
  1250. public void SetSocketOption(SocketOptionLevel level,
  1251. SocketOptionName name,
  1252. object opt_value) {
  1253. if(opt_value==null) {
  1254. throw new ArgumentNullException();
  1255. }
  1256. int error;
  1257. /* Passing a bool as the third parameter to
  1258. * SetSocketOption causes this overload to be
  1259. * used when in fact we want to pass the value
  1260. * to the runtime as an int.
  1261. */
  1262. if (opt_value is System.Boolean) {
  1263. bool bool_val = (bool) opt_value;
  1264. int int_val = (bool_val) ? 1 : 0;
  1265. SetSocketOption_internal (socket, level, name, null, null, int_val, out error);
  1266. } else {
  1267. SetSocketOption_internal (socket, level, name, opt_value, null, 0, out error);
  1268. }
  1269. if (error != 0) {
  1270. throw new SocketException (error);
  1271. }
  1272. }
  1273. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1274. private extern static void Shutdown_internal(IntPtr socket, SocketShutdown how, out int error);
  1275. public void Shutdown(SocketShutdown how) {
  1276. int error;
  1277. Shutdown_internal(socket, how, out error);
  1278. if (error != 0) {
  1279. throw new SocketException (error);
  1280. }
  1281. }
  1282. public override int GetHashCode ()
  1283. {
  1284. return (int) socket;
  1285. }
  1286. private bool disposed;
  1287. protected virtual void Dispose(bool explicitDisposing) {
  1288. if (!disposed) {
  1289. int error;
  1290. disposed = true;
  1291. connected = false;
  1292. if (!explicitDisposing) {
  1293. closed = true;
  1294. Close_internal (socket, out error);
  1295. if (error != 0) {
  1296. throw new SocketException (error);
  1297. }
  1298. return;
  1299. }
  1300. if (Interlocked.CompareExchange (ref pendingEnds, 0, 0) == 0) {
  1301. closed = true;
  1302. Close_internal (socket, out error);
  1303. if (error != 0) {
  1304. throw new SocketException (error);
  1305. }
  1306. } else {
  1307. Interlocked.CompareExchange (ref closeDelayed, 1, 0);
  1308. }
  1309. }
  1310. }
  1311. void IDisposable.Dispose ()
  1312. {
  1313. Dispose (true);
  1314. GC.SuppressFinalize (this);
  1315. }
  1316. ~Socket () {
  1317. Dispose(false);
  1318. }
  1319. static Hashtable asyncObjects;
  1320. static void KeepReference (object o)
  1321. {
  1322. lock (typeof (Socket)) {
  1323. if (asyncObjects == null)
  1324. asyncObjects = new Hashtable ();
  1325. asyncObjects [o] = o;
  1326. }
  1327. }
  1328. static void RemoveReference (object o)
  1329. {
  1330. lock (typeof (Socket)) {
  1331. if (asyncObjects == null)
  1332. return;
  1333. asyncObjects.Remove (o);
  1334. }
  1335. }
  1336. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1337. extern static bool GetSupportsAsync ();
  1338. static bool FakeGetSupportsAsync ()
  1339. {
  1340. if (Environment.GetEnvironmentVariable ("MONO_ENABLE_SOCKET_AIO") != null)
  1341. return GetSupportsAsync ();
  1342. return false;
  1343. }
  1344. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1345. extern static void AsyncReceiveInternal (SocketAsyncResult ares, out int error);
  1346. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1347. extern static void AsyncSendInternal (SocketAsyncResult ares, out int error);
  1348. }
  1349. }