Socket.cs 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738
  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. connected = false;
  1076. throw new SocketException (error);
  1077. }
  1078. connected = true;
  1079. return ret;
  1080. }
  1081. public int ReceiveFrom (byte [] buf, ref EndPoint remote_end)
  1082. {
  1083. if (buf == null)
  1084. throw new ArgumentNullException ("buf");
  1085. if (remote_end == null)
  1086. throw new ArgumentNullException ("remote_end");
  1087. return ReceiveFrom_nochecks (buf, 0, buf.Length, SocketFlags.None, ref remote_end);
  1088. }
  1089. public int ReceiveFrom (byte [] buf, SocketFlags flags, ref EndPoint remote_end)
  1090. {
  1091. if (buf == null)
  1092. throw new ArgumentNullException ("buf");
  1093. if (remote_end == null)
  1094. throw new ArgumentNullException ("remote_end");
  1095. return ReceiveFrom_nochecks (buf, 0, buf.Length, flags, ref remote_end);
  1096. }
  1097. public int ReceiveFrom (byte [] buf, int size, SocketFlags flags,
  1098. ref EndPoint remote_end)
  1099. {
  1100. if (buf == null)
  1101. throw new ArgumentNullException ("buf");
  1102. if (remote_end == null)
  1103. throw new ArgumentNullException ("remote_end");
  1104. if (size < 0 || size > buf.Length)
  1105. throw new ArgumentOutOfRangeException ("size");
  1106. return ReceiveFrom_nochecks (buf, 0, size, flags, ref remote_end);
  1107. }
  1108. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1109. private extern static int RecvFrom_internal(IntPtr sock,
  1110. byte[] buffer,
  1111. int offset,
  1112. int count,
  1113. SocketFlags flags,
  1114. ref SocketAddress sockaddr,
  1115. out int error);
  1116. public int ReceiveFrom (byte [] buf, int offset, int size, SocketFlags flags,
  1117. ref EndPoint remote_end)
  1118. {
  1119. if (buf == null)
  1120. throw new ArgumentNullException ("buf");
  1121. if (remote_end == null)
  1122. throw new ArgumentNullException ("remote_end");
  1123. if (offset < 0 || offset > buf.Length)
  1124. throw new ArgumentOutOfRangeException ("offset");
  1125. if (size < 0 || offset + size > buf.Length)
  1126. throw new ArgumentOutOfRangeException ("size");
  1127. return ReceiveFrom_nochecks (buf, offset, size, flags, ref remote_end);
  1128. }
  1129. int ReceiveFrom_nochecks (byte [] buf, int offset, int size, SocketFlags flags,
  1130. ref EndPoint remote_end)
  1131. {
  1132. SocketAddress sockaddr = remote_end.Serialize();
  1133. int cnt, error;
  1134. cnt = RecvFrom_internal (socket, buf, offset, size, flags, ref sockaddr, out error);
  1135. if (error != 0) {
  1136. connected = false;
  1137. throw new SocketException (error);
  1138. }
  1139. connected = true;
  1140. // If sockaddr is null then we're a connection
  1141. // oriented protocol and should ignore the
  1142. // remote_end parameter (see MSDN
  1143. // documentation for Socket.ReceiveFrom(...) )
  1144. if ( sockaddr != null ) {
  1145. // Stupidly, EndPoint.Create() is an
  1146. // instance method
  1147. remote_end = remote_end.Create (sockaddr);
  1148. }
  1149. return cnt;
  1150. }
  1151. public int Send (byte [] buf)
  1152. {
  1153. if (buf == null)
  1154. throw new ArgumentNullException ("buf");
  1155. return Send_nochecks (buf, 0, buf.Length, SocketFlags.None);
  1156. }
  1157. public int Send (byte [] buf, SocketFlags flags)
  1158. {
  1159. if (buf == null)
  1160. throw new ArgumentNullException ("buf");
  1161. return Send_nochecks (buf, 0, buf.Length, flags);
  1162. }
  1163. public int Send (byte [] buf, int size, SocketFlags flags)
  1164. {
  1165. if (buf == null)
  1166. throw new ArgumentNullException ("buf");
  1167. if (size < 0 || size > buf.Length)
  1168. throw new ArgumentOutOfRangeException ("size");
  1169. return Send_nochecks (buf, 0, size, flags);
  1170. }
  1171. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1172. private extern static int Send_internal(IntPtr sock,
  1173. byte[] buf, int offset,
  1174. int count,
  1175. SocketFlags flags,
  1176. out int error);
  1177. public int Send (byte [] buf, int offset, int size, SocketFlags flags)
  1178. {
  1179. if (buf == null)
  1180. throw new ArgumentNullException ("buffer");
  1181. if (offset < 0 || offset > buf.Length)
  1182. throw new ArgumentOutOfRangeException ("offset");
  1183. if (size < 0 || offset + size > buf.Length)
  1184. throw new ArgumentOutOfRangeException ("size");
  1185. return Send_nochecks (buf, offset, size, flags);
  1186. }
  1187. int Send_nochecks (byte [] buf, int offset, int size, SocketFlags flags)
  1188. {
  1189. if (size == 0)
  1190. return 0;
  1191. int ret, error;
  1192. ret = Send_internal (socket, buf, offset, size, flags, out error);
  1193. if (error != 0) {
  1194. connected = false;
  1195. throw new SocketException (error);
  1196. }
  1197. connected = true;
  1198. return ret;
  1199. }
  1200. public int SendTo (byte [] buffer, 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. return SendTo_nochecks (buffer, 0, buffer.Length, SocketFlags.None, remote_end);
  1207. }
  1208. public int SendTo (byte [] buffer, SocketFlags flags, EndPoint remote_end)
  1209. {
  1210. if (buffer == null)
  1211. throw new ArgumentNullException ("buffer");
  1212. if (remote_end == null)
  1213. throw new ArgumentNullException ("remote_end");
  1214. return SendTo_nochecks (buffer, 0, buffer.Length, flags, remote_end);
  1215. }
  1216. public int SendTo (byte [] buffer, int size, SocketFlags flags, EndPoint remote_end)
  1217. {
  1218. if (buffer == null)
  1219. throw new ArgumentNullException ("buffer");
  1220. if (remote_end == null)
  1221. throw new ArgumentNullException ("remote_end");
  1222. if (size < 0 || size > buffer.Length)
  1223. throw new ArgumentOutOfRangeException ("size");
  1224. return SendTo_nochecks (buffer, 0, size, flags, remote_end);
  1225. }
  1226. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1227. private extern static int SendTo_internal(IntPtr sock,
  1228. byte[] buffer,
  1229. int offset,
  1230. int count,
  1231. SocketFlags flags,
  1232. SocketAddress sa,
  1233. out int error);
  1234. public int SendTo (byte [] buffer, int offset, int size, SocketFlags flags,
  1235. EndPoint remote_end)
  1236. {
  1237. if (buffer == null)
  1238. throw new ArgumentNullException ("buffer");
  1239. if (remote_end == null)
  1240. throw new ArgumentNullException("remote_end");
  1241. if (offset < 0 || offset > buffer.Length)
  1242. throw new ArgumentOutOfRangeException ("offset");
  1243. if (size < 0 || offset + size > buffer.Length)
  1244. throw new ArgumentOutOfRangeException ("size");
  1245. return SendTo_nochecks (buffer, offset, size, flags, remote_end);
  1246. }
  1247. int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags,
  1248. EndPoint remote_end)
  1249. {
  1250. SocketAddress sockaddr = remote_end.Serialize ();
  1251. int ret, error;
  1252. ret = SendTo_internal (socket, buffer, offset, size, flags, sockaddr, out error);
  1253. if (error != 0) {
  1254. connected = false;
  1255. throw new SocketException (error);
  1256. }
  1257. connected = true;
  1258. return ret;
  1259. }
  1260. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1261. private extern static void SetSocketOption_internal (IntPtr socket, SocketOptionLevel level,
  1262. SocketOptionName name, object obj_val,
  1263. byte [] byte_val, int int_val,
  1264. out int error);
  1265. public void SetSocketOption(SocketOptionLevel level,
  1266. SocketOptionName name,
  1267. byte[] opt_value) {
  1268. int error;
  1269. SetSocketOption_internal(socket, level, name, null,
  1270. opt_value, 0, out error);
  1271. if (error != 0) {
  1272. throw new SocketException (error);
  1273. }
  1274. }
  1275. public void SetSocketOption(SocketOptionLevel level,
  1276. SocketOptionName name,
  1277. int opt_value) {
  1278. int error;
  1279. SetSocketOption_internal(socket, level, name, null,
  1280. null, opt_value, out error);
  1281. if (error != 0) {
  1282. throw new SocketException (error);
  1283. }
  1284. }
  1285. public void SetSocketOption(SocketOptionLevel level,
  1286. SocketOptionName name,
  1287. object opt_value) {
  1288. if(opt_value==null) {
  1289. throw new ArgumentNullException();
  1290. }
  1291. int error;
  1292. /* Passing a bool as the third parameter to
  1293. * SetSocketOption causes this overload to be
  1294. * used when in fact we want to pass the value
  1295. * to the runtime as an int.
  1296. */
  1297. if (opt_value is System.Boolean) {
  1298. bool bool_val = (bool) opt_value;
  1299. int int_val = (bool_val) ? 1 : 0;
  1300. SetSocketOption_internal (socket, level, name, null, null, int_val, out error);
  1301. } else {
  1302. SetSocketOption_internal (socket, level, name, opt_value, null, 0, out error);
  1303. }
  1304. if (error != 0) {
  1305. throw new SocketException (error);
  1306. }
  1307. }
  1308. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1309. private extern static void Shutdown_internal(IntPtr socket, SocketShutdown how, out int error);
  1310. public void Shutdown(SocketShutdown how) {
  1311. int error;
  1312. Shutdown_internal(socket, how, out error);
  1313. if (error != 0) {
  1314. throw new SocketException (error);
  1315. }
  1316. }
  1317. public override int GetHashCode ()
  1318. {
  1319. return (int) socket;
  1320. }
  1321. private bool disposed;
  1322. protected virtual void Dispose(bool explicitDisposing) {
  1323. if (!disposed) {
  1324. int error;
  1325. disposed = true;
  1326. connected = false;
  1327. if (!explicitDisposing) {
  1328. closed = true;
  1329. Close_internal (socket, out error);
  1330. if (error != 0) {
  1331. throw new SocketException (error);
  1332. }
  1333. return;
  1334. }
  1335. if (Interlocked.CompareExchange (ref pendingEnds, 0, 0) == 0) {
  1336. closed = true;
  1337. Close_internal (socket, out error);
  1338. if (error != 0) {
  1339. throw new SocketException (error);
  1340. }
  1341. } else {
  1342. Interlocked.CompareExchange (ref closeDelayed, 1, 0);
  1343. }
  1344. }
  1345. }
  1346. void IDisposable.Dispose ()
  1347. {
  1348. Dispose (true);
  1349. GC.SuppressFinalize (this);
  1350. }
  1351. ~Socket () {
  1352. Dispose(false);
  1353. }
  1354. static Hashtable asyncObjects;
  1355. static void KeepReference (object o)
  1356. {
  1357. lock (typeof (Socket)) {
  1358. if (asyncObjects == null)
  1359. asyncObjects = new Hashtable ();
  1360. asyncObjects [o] = o;
  1361. }
  1362. }
  1363. static void RemoveReference (object o)
  1364. {
  1365. lock (typeof (Socket)) {
  1366. if (asyncObjects == null)
  1367. return;
  1368. asyncObjects.Remove (o);
  1369. }
  1370. }
  1371. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1372. extern static bool GetSupportsAsync ();
  1373. static bool FakeGetSupportsAsync ()
  1374. {
  1375. if (Environment.GetEnvironmentVariable ("MONO_ENABLE_SOCKET_AIO") != null)
  1376. return GetSupportsAsync ();
  1377. return false;
  1378. }
  1379. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1380. extern static void AsyncReceiveInternal (SocketAsyncResult ares, out int error);
  1381. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1382. extern static void AsyncSendInternal (SocketAsyncResult ares, out int error);
  1383. }
  1384. }