Socket.cs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134
  1. // System.Net.Sockets.Socket.cs
  2. //
  3. // Authors:
  4. // Phillip Pearson ([email protected])
  5. // Dick Porter <[email protected]>
  6. //
  7. // Copyright (C) 2001, 2002 Phillip Pearson and Ximian, Inc.
  8. // http://www.myelin.co.nz
  9. //
  10. using System;
  11. using System.Net;
  12. using System.Collections;
  13. using System.Runtime.CompilerServices;
  14. using System.Threading;
  15. using System.Reflection;
  16. using System.IO;
  17. namespace System.Net.Sockets
  18. {
  19. public class Socket : IDisposable
  20. {
  21. private sealed class SocketAsyncResult: IAsyncResult
  22. {
  23. private object state;
  24. private WaitHandle waithandle;
  25. private bool completed_sync, completed;
  26. private Worker worker;
  27. public SocketAsyncResult(object state) {
  28. this.state=state;
  29. waithandle=new ManualResetEvent(false);
  30. completed_sync=completed=false;
  31. }
  32. public object AsyncState {
  33. get {
  34. return(state);
  35. }
  36. }
  37. public WaitHandle AsyncWaitHandle {
  38. get {
  39. return(waithandle);
  40. }
  41. set {
  42. waithandle=value;
  43. }
  44. }
  45. public bool CompletedSynchronously {
  46. get {
  47. return(completed_sync);
  48. }
  49. }
  50. public bool IsCompleted {
  51. get {
  52. return(completed);
  53. }
  54. set {
  55. completed=value;
  56. }
  57. }
  58. public Worker Worker {
  59. get {
  60. return(worker);
  61. }
  62. set {
  63. worker=value;
  64. }
  65. }
  66. }
  67. private sealed class Worker
  68. {
  69. private AsyncCallback callback;
  70. private SocketAsyncResult result;
  71. private Socket socket;
  72. // Parameters
  73. private EndPoint endpoint; // Connect,ReceiveFrom,SendTo
  74. private byte[] buffer; // Receive,ReceiveFrom,Send,SendTo
  75. private int offset; // Receive,ReceiveFrom,Send,SendTo
  76. private int size; // Receive,ReceiveFrom,Send,SendTo
  77. private SocketFlags sockflags; // Receive,ReceiveFrom,Send,SendTo
  78. // Return values
  79. private Socket acc_socket;
  80. private int total;
  81. // For Accept
  82. public Worker(Socket req_sock,
  83. AsyncCallback req_callback,
  84. SocketAsyncResult req_result)
  85. : this(req_sock, null, 0, 0, SocketFlags.None,
  86. null, req_callback, req_result) {}
  87. // For Connect
  88. public Worker(Socket req_sock, EndPoint req_endpoint,
  89. AsyncCallback req_callback,
  90. SocketAsyncResult req_result)
  91. : this(req_sock, null, 0, 0, SocketFlags.None,
  92. req_endpoint, req_callback,
  93. req_result) {}
  94. // For Receive and Send
  95. public Worker(Socket req_sock, byte[] req_buffer,
  96. int req_offset, int req_size,
  97. SocketFlags req_sockflags,
  98. AsyncCallback req_callback,
  99. SocketAsyncResult req_result)
  100. : this(req_sock, req_buffer, req_offset,
  101. req_size, req_sockflags, null,
  102. req_callback, req_result) {}
  103. // For ReceiveFrom and SendTo
  104. public Worker(Socket req_sock, byte[] req_buffer,
  105. int req_offset, int req_size,
  106. SocketFlags req_sockflags,
  107. EndPoint req_endpoint,
  108. AsyncCallback req_callback,
  109. SocketAsyncResult req_result) {
  110. socket=req_sock;
  111. buffer=req_buffer;
  112. offset=req_offset;
  113. size=req_size;
  114. sockflags=req_sockflags;
  115. endpoint=req_endpoint;
  116. callback=req_callback;
  117. result=req_result;
  118. }
  119. private void End() {
  120. ((ManualResetEvent)result.AsyncWaitHandle).Set();
  121. result.IsCompleted=true;
  122. if (callback != null)
  123. callback(result);
  124. }
  125. public void Accept() {
  126. lock(result) {
  127. acc_socket=socket.Accept();
  128. End();
  129. }
  130. }
  131. public void Connect() {
  132. lock(result) {
  133. if (socket.Blocking) {
  134. socket.Connect(endpoint);
  135. End ();
  136. return;
  137. }
  138. SocketException rethrow = null;
  139. try {
  140. socket.Connect (endpoint);
  141. } catch (SocketException e) {
  142. //WSAEINPROGRESS
  143. if (e.NativeErrorCode != 10036)
  144. throw;
  145. socket.Poll (-1, SelectMode.SelectWrite);
  146. try {
  147. socket.Connect (endpoint);
  148. } catch (SocketException e2) {
  149. rethrow = e2;
  150. }
  151. }
  152. End ();
  153. if (rethrow != null)
  154. throw rethrow;
  155. }
  156. }
  157. public void Receive() {
  158. lock(result) {
  159. if (socket.Blocking) {
  160. total=socket.Receive(buffer, offset,
  161. size, sockflags);
  162. End();
  163. return;
  164. }
  165. SocketException rethrow = null;
  166. try {
  167. total = socket.Receive (buffer, offset, size, sockflags);
  168. } catch (SocketException e) {
  169. //WSAEWOULDBLOCK
  170. if (e.NativeErrorCode != 10035)
  171. throw;
  172. socket.Poll (-1, SelectMode.SelectRead);
  173. try {
  174. total = socket.Receive (buffer, offset, size, sockflags);
  175. } catch (SocketException e2) {
  176. rethrow = e2;
  177. }
  178. }
  179. End ();
  180. if (rethrow != null)
  181. throw rethrow;
  182. }
  183. }
  184. public void ReceiveFrom() {
  185. lock(result) {
  186. total=socket.ReceiveFrom(buffer,
  187. offset, size,
  188. sockflags,
  189. ref endpoint);
  190. End();
  191. }
  192. }
  193. public void Send() {
  194. lock(result) {
  195. total=socket.Send(buffer, offset, size,
  196. sockflags);
  197. End();
  198. }
  199. }
  200. public void SendTo() {
  201. lock(result) {
  202. total=socket.SendTo(buffer, offset,
  203. size, sockflags,
  204. endpoint);
  205. End();
  206. }
  207. }
  208. public EndPoint EndPoint {
  209. get {
  210. return(endpoint);
  211. }
  212. }
  213. public Socket Socket {
  214. get {
  215. return(acc_socket);
  216. }
  217. }
  218. public int Total {
  219. get {
  220. return(total);
  221. }
  222. }
  223. }
  224. /* the field "socket" is looked up by name by the runtime */
  225. private IntPtr socket;
  226. private AddressFamily address_family;
  227. private SocketType socket_type;
  228. private ProtocolType protocol_type;
  229. private bool blocking=true;
  230. /*
  231. * These two fields are looked up by name by the runtime, don't change
  232. * their name without also updating the runtime code.
  233. */
  234. private static int ipv4Supported = -1, ipv6Supported = -1;
  235. /* When true, the socket was connected at the time of
  236. * the last IO operation
  237. */
  238. private bool connected=false;
  239. /* Used in LocalEndPoint and RemoteEndPoint if the
  240. * Mono.Posix assembly is available
  241. */
  242. private static object unixendpoint=null;
  243. private static Type unixendpointtype=null;
  244. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  245. private extern static void Select_internal(ref Socket[] read,
  246. ref Socket[] write,
  247. ref Socket[] err,
  248. int timeout);
  249. public static void Select(IList read_list, IList write_list,
  250. IList err_list, int time_us) {
  251. if(read_list==null &&
  252. write_list==null &&
  253. err_list==null) {
  254. throw new ArgumentNullException();
  255. }
  256. int read_count = 0, write_count = 0, err_count = 0;
  257. Socket[] read_arr = null;
  258. Socket[] write_arr = null;
  259. Socket[] err_arr = null;
  260. if (read_list!=null)
  261. read_count=read_list.Count;
  262. if (read_count != 0)
  263. read_arr=new Socket[read_count];
  264. if (write_list!=null)
  265. write_count=write_list.Count;
  266. if (write_count != 0)
  267. write_arr=new Socket[write_count];
  268. if (err_list!=null)
  269. err_count=err_list.Count;
  270. if (err_count != 0)
  271. err_arr=new Socket[err_count];
  272. int i;
  273. if (read_count != 0) {
  274. i=0;
  275. foreach (Socket s in read_list) {
  276. read_arr[i]=s;
  277. i++;
  278. }
  279. }
  280. if (write_count != 0) {
  281. i=0;
  282. foreach (Socket s in write_list) {
  283. write_arr[i]=s;
  284. i++;
  285. }
  286. }
  287. if (err_count != 0) {
  288. i=0;
  289. foreach (Socket s in err_list) {
  290. err_arr[i]=s;
  291. i++;
  292. }
  293. }
  294. Select_internal(ref read_arr, ref write_arr,
  295. ref err_arr, time_us);
  296. if(read_list!=null) {
  297. read_list.Clear();
  298. for(i=0; i<read_arr.Length; i++) {
  299. read_list.Add(read_arr[i]);
  300. }
  301. }
  302. if(write_list!=null) {
  303. write_list.Clear();
  304. for(i=0; i<write_arr.Length; i++) {
  305. write_list.Add(write_arr[i]);
  306. }
  307. }
  308. if(err_list!=null) {
  309. err_list.Clear();
  310. for(i=0; i<err_arr.Length; i++) {
  311. err_list.Add(err_arr[i]);
  312. }
  313. }
  314. }
  315. static Socket() {
  316. Assembly ass;
  317. try {
  318. ass=Assembly.Load("Mono.Posix");
  319. } catch (FileNotFoundException) {
  320. return;
  321. }
  322. unixendpointtype=ass.GetType("Mono.Posix.UnixEndPoint");
  323. /* The endpoint Create() method is an instance
  324. * method :-(
  325. */
  326. Type[] arg_types=new Type[1];
  327. arg_types[0]=typeof(string);
  328. ConstructorInfo cons=unixendpointtype.GetConstructor(arg_types);
  329. object[] args=new object[1];
  330. args[0]="";
  331. unixendpoint=cons.Invoke(args);
  332. }
  333. // private constructor used by Accept, which already
  334. // has a socket handle to use
  335. private Socket(AddressFamily family, SocketType type,
  336. ProtocolType proto, IntPtr sock) {
  337. address_family=family;
  338. socket_type=type;
  339. protocol_type=proto;
  340. socket=sock;
  341. connected=true;
  342. }
  343. // Creates a new system socket, returning the handle
  344. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  345. private extern IntPtr Socket_internal(AddressFamily family,
  346. SocketType type,
  347. ProtocolType proto);
  348. public Socket(AddressFamily family, SocketType type,
  349. ProtocolType proto) {
  350. address_family=family;
  351. socket_type=type;
  352. protocol_type=proto;
  353. socket=Socket_internal(family, type, proto);
  354. }
  355. public AddressFamily AddressFamily {
  356. get {
  357. return(address_family);
  358. }
  359. }
  360. // Returns the amount of data waiting to be read on socket
  361. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  362. private extern static int Available_internal(IntPtr socket);
  363. public int Available {
  364. get {
  365. return(Available_internal(socket));
  366. }
  367. }
  368. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  369. private extern static void Blocking_internal(IntPtr socket,
  370. bool block);
  371. public bool Blocking {
  372. get {
  373. return(blocking);
  374. }
  375. set {
  376. Blocking_internal(socket, value);
  377. blocking=value;
  378. }
  379. }
  380. public bool Connected {
  381. get {
  382. return(connected);
  383. }
  384. }
  385. public IntPtr Handle {
  386. get {
  387. return(socket);
  388. }
  389. }
  390. // Returns the local endpoint details in addr and port
  391. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  392. private extern static SocketAddress LocalEndPoint_internal(IntPtr socket);
  393. [MonoTODO("Support non-IP endpoints")]
  394. public EndPoint LocalEndPoint {
  395. get {
  396. SocketAddress sa;
  397. sa=LocalEndPoint_internal(socket);
  398. if(sa.Family==AddressFamily.InterNetwork || sa.Family==AddressFamily.InterNetworkV6) {
  399. // Stupidly, EndPoint.Create() is an
  400. // instance method
  401. return new IPEndPoint(0, 0).Create(sa);
  402. } else if (sa.Family==AddressFamily.Unix &&
  403. unixendpoint!=null) {
  404. return((EndPoint)unixendpointtype.InvokeMember("Create", BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public, null, unixendpoint, new object[] {sa}));
  405. } else {
  406. throw new NotImplementedException();
  407. }
  408. }
  409. }
  410. public ProtocolType ProtocolType {
  411. get {
  412. return(protocol_type);
  413. }
  414. }
  415. // Returns the remote endpoint details in addr and port
  416. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  417. private extern static SocketAddress RemoteEndPoint_internal(IntPtr socket);
  418. [MonoTODO("Support non-IP endpoints")]
  419. public EndPoint RemoteEndPoint {
  420. get {
  421. SocketAddress sa;
  422. sa=RemoteEndPoint_internal(socket);
  423. if(sa.Family==AddressFamily.InterNetwork || sa.Family==AddressFamily.InterNetworkV6 ) {
  424. // Stupidly, EndPoint.Create() is an
  425. // instance method
  426. return new IPEndPoint(0, 0).Create(sa);
  427. } else if (sa.Family==AddressFamily.Unix &&
  428. unixendpoint!=null) {
  429. return((EndPoint)unixendpointtype.InvokeMember("Create", BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public, null, unixendpoint, new object[] {sa}));
  430. } else {
  431. throw new NotImplementedException();
  432. }
  433. }
  434. }
  435. public SocketType SocketType {
  436. get {
  437. return(socket_type);
  438. }
  439. }
  440. #if NET_1_1
  441. public static bool SupportsIPv4 {
  442. get {
  443. CheckProtocolSupport();
  444. return ipv4Supported == 1;
  445. }
  446. }
  447. public static bool SupportsIPv6 {
  448. get {
  449. CheckProtocolSupport();
  450. return ipv6Supported == 1;
  451. }
  452. }
  453. #else
  454. internal static bool SupportsIPv4
  455. {
  456. get
  457. {
  458. return true;
  459. }
  460. }
  461. internal static bool SupportsIPv6
  462. {
  463. get
  464. {
  465. return false;
  466. }
  467. }
  468. #endif
  469. internal static void CheckProtocolSupport()
  470. {
  471. if(ipv4Supported == -1) {
  472. try {
  473. Socket tmp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  474. tmp.Close();
  475. ipv4Supported = 1;
  476. }
  477. catch {
  478. ipv4Supported = 0;
  479. }
  480. }
  481. if(ipv6Supported == -1) {
  482. NetConfig config = (NetConfig)System.Configuration.ConfigurationSettings.GetConfig("system.net/settings");
  483. if(config != null)
  484. ipv6Supported = config.ipv6Enabled?-1:0;
  485. if(ipv6Supported != 0) {
  486. try {
  487. Socket tmp = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
  488. tmp.Close();
  489. ipv6Supported = 1;
  490. }
  491. catch { }
  492. }
  493. }
  494. }
  495. // Creates a new system socket, returning the handle
  496. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  497. private extern static IntPtr Accept_internal(IntPtr sock);
  498. public Socket Accept() {
  499. IntPtr sock=Accept_internal(socket);
  500. return(new Socket(this.AddressFamily, this.SocketType,
  501. this.ProtocolType, sock));
  502. }
  503. public IAsyncResult BeginAccept(AsyncCallback callback,
  504. object state) {
  505. SocketAsyncResult req=new SocketAsyncResult(state);
  506. Worker worker=new Worker(this, callback, req);
  507. req.Worker=worker;
  508. Thread child=new Thread(new ThreadStart(worker.Accept));
  509. child.Start();
  510. return(req);
  511. }
  512. public IAsyncResult BeginConnect(EndPoint end_point,
  513. AsyncCallback callback,
  514. object state) {
  515. SocketAsyncResult req=new SocketAsyncResult(state);
  516. Worker worker=new Worker(this, end_point, callback,
  517. req);
  518. req.Worker=worker;
  519. Thread child=new Thread(new ThreadStart(worker.Connect));
  520. child.Start();
  521. return(req);
  522. }
  523. public IAsyncResult BeginReceive(byte[] buffer, int offset,
  524. int size,
  525. SocketFlags socket_flags,
  526. AsyncCallback callback,
  527. object state) {
  528. SocketAsyncResult req=new SocketAsyncResult(state);
  529. Worker worker=new Worker(this, buffer, offset, size,
  530. socket_flags, callback, req);
  531. req.Worker=worker;
  532. Thread child=new Thread(new ThreadStart(worker.Receive));
  533. child.Start();
  534. return(req);
  535. }
  536. public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset,
  537. int size,
  538. SocketFlags socket_flags,
  539. ref EndPoint remote_end,
  540. AsyncCallback callback,
  541. object state) {
  542. SocketAsyncResult req=new SocketAsyncResult(state);
  543. Worker worker=new Worker(this, buffer, offset, size,
  544. socket_flags, remote_end,
  545. callback, req);
  546. req.Worker=worker;
  547. Thread child=new Thread(new ThreadStart(worker.ReceiveFrom));
  548. child.Start();
  549. return(req);
  550. }
  551. public IAsyncResult BeginSend(byte[] buffer, int offset,
  552. int size,
  553. SocketFlags socket_flags,
  554. AsyncCallback callback,
  555. object state) {
  556. SocketAsyncResult req=new SocketAsyncResult(state);
  557. Worker worker=new Worker(this, buffer, offset, size,
  558. socket_flags, callback, req);
  559. req.Worker=worker;
  560. Thread child=new Thread(new ThreadStart(worker.Send));
  561. child.Start();
  562. return(req);
  563. }
  564. public IAsyncResult BeginSendTo(byte[] buffer, int offset,
  565. int size,
  566. SocketFlags socket_flags,
  567. EndPoint remote_end,
  568. AsyncCallback callback,
  569. object state) {
  570. SocketAsyncResult req=new SocketAsyncResult(state);
  571. Worker worker=new Worker(this, buffer, offset, size,
  572. socket_flags, remote_end,
  573. callback, req);
  574. req.Worker=worker;
  575. Thread child=new Thread(new ThreadStart(worker.SendTo));
  576. child.Start();
  577. return(req);
  578. }
  579. // Creates a new system socket, returning the handle
  580. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  581. private extern static void Bind_internal(IntPtr sock,
  582. SocketAddress sa);
  583. public void Bind(EndPoint local_end) {
  584. if(local_end==null) {
  585. throw new ArgumentNullException();
  586. }
  587. Bind_internal(socket, local_end.Serialize());
  588. }
  589. // Closes the socket
  590. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  591. private extern static void Close_internal(IntPtr socket);
  592. public void Close() {
  593. this.Dispose();
  594. }
  595. // Connects to the remote address
  596. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  597. private extern static void Connect_internal(IntPtr sock,
  598. SocketAddress sa);
  599. public void Connect(EndPoint remote_end) {
  600. if(remote_end==null) {
  601. throw new ArgumentNullException();
  602. }
  603. Connect_internal(socket, remote_end.Serialize());
  604. connected=true;
  605. }
  606. public Socket EndAccept(IAsyncResult result) {
  607. SocketAsyncResult req=(SocketAsyncResult)result;
  608. result.AsyncWaitHandle.WaitOne();
  609. return(req.Worker.Socket);
  610. }
  611. public void EndConnect(IAsyncResult result) {
  612. SocketAsyncResult req=(SocketAsyncResult)result;
  613. result.AsyncWaitHandle.WaitOne();
  614. }
  615. public int EndReceive(IAsyncResult result) {
  616. SocketAsyncResult req=(SocketAsyncResult)result;
  617. result.AsyncWaitHandle.WaitOne();
  618. return(req.Worker.Total);
  619. }
  620. public int EndReceiveFrom(IAsyncResult result,
  621. ref EndPoint end_point) {
  622. SocketAsyncResult req=(SocketAsyncResult)result;
  623. result.AsyncWaitHandle.WaitOne();
  624. end_point=req.Worker.EndPoint;
  625. return(req.Worker.Total);
  626. }
  627. public int EndSend(IAsyncResult result) {
  628. SocketAsyncResult req=(SocketAsyncResult)result;
  629. result.AsyncWaitHandle.WaitOne();
  630. return(req.Worker.Total);
  631. }
  632. public int EndSendTo(IAsyncResult result) {
  633. SocketAsyncResult req=(SocketAsyncResult)result;
  634. result.AsyncWaitHandle.WaitOne();
  635. return(req.Worker.Total);
  636. }
  637. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  638. private extern static void GetSocketOption_obj_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, out object obj_val);
  639. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  640. private extern static void GetSocketOption_arr_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val);
  641. public object GetSocketOption(SocketOptionLevel level,
  642. SocketOptionName name) {
  643. object obj_val;
  644. GetSocketOption_obj_internal(socket, level, name,
  645. out obj_val);
  646. if(name==SocketOptionName.Linger) {
  647. return((LingerOption)obj_val);
  648. } else if (name==SocketOptionName.AddMembership ||
  649. name==SocketOptionName.DropMembership) {
  650. return((MulticastOption)obj_val);
  651. } else {
  652. return((int)obj_val);
  653. }
  654. }
  655. public void GetSocketOption(SocketOptionLevel level,
  656. SocketOptionName name,
  657. byte[] opt_value) {
  658. int opt_value_len=opt_value.Length;
  659. GetSocketOption_arr_internal(socket, level, name,
  660. ref opt_value);
  661. }
  662. public byte[] GetSocketOption(SocketOptionLevel level,
  663. SocketOptionName name,
  664. int length) {
  665. byte[] byte_val=new byte[length];
  666. GetSocketOption_arr_internal(socket, level, name,
  667. ref byte_val);
  668. return(byte_val);
  669. }
  670. [MonoTODO("Totally undocumented")]
  671. public int IOControl(int ioctl_code, byte[] in_value,
  672. byte[] out_value) {
  673. throw new NotImplementedException();
  674. }
  675. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  676. private extern static void Listen_internal(IntPtr sock,
  677. int backlog);
  678. public void Listen(int backlog) {
  679. Listen_internal(socket, backlog);
  680. }
  681. /* The docs for Poll() are a bit lightweight too, but
  682. * it seems to be just a simple wrapper around Select.
  683. */
  684. public bool Poll(int time_us, SelectMode mode) {
  685. Socket [] socketlist = new Socket []{this};
  686. Socket [] n = null;
  687. switch(mode) {
  688. case SelectMode.SelectError:
  689. Select_internal (ref n, ref n, ref socketlist, time_us);
  690. break;
  691. case SelectMode.SelectRead:
  692. Select_internal (ref socketlist, ref n, ref n, time_us);
  693. break;
  694. case SelectMode.SelectWrite:
  695. Select_internal (ref n, ref socketlist, ref n, time_us);
  696. break;
  697. default:
  698. throw new NotSupportedException();
  699. }
  700. return (socketlist.Length == 1);
  701. }
  702. public int Receive(byte[] buf) {
  703. return(Receive(buf, 0, buf.Length, SocketFlags.None));
  704. }
  705. public int Receive(byte[] buf, SocketFlags flags) {
  706. return(Receive(buf, 0, buf.Length, flags));
  707. }
  708. public int Receive(byte[] buf, int size, SocketFlags flags) {
  709. return(Receive(buf, 0, size, flags));
  710. }
  711. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  712. private extern static int Receive_internal(IntPtr sock,
  713. byte[] buffer,
  714. int offset,
  715. int count,
  716. SocketFlags flags);
  717. public int Receive(byte[] buf, int offset, int size,
  718. SocketFlags flags) {
  719. if(buf==null) {
  720. throw new ArgumentNullException("buffer is null");
  721. }
  722. if(offset<0 || offset > buf.Length) {
  723. throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
  724. }
  725. if(size<0 || offset+size > buf.Length) {
  726. throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
  727. }
  728. int ret;
  729. try {
  730. ret=Receive_internal(socket, buf, offset,
  731. size, flags);
  732. } catch(SocketException) {
  733. connected=false;
  734. throw;
  735. }
  736. connected=true;
  737. return(ret);
  738. }
  739. public int ReceiveFrom(byte[] buf, ref EndPoint remote_end) {
  740. return(ReceiveFrom(buf, 0, buf.Length,
  741. SocketFlags.None, ref remote_end));
  742. }
  743. public int ReceiveFrom(byte[] buf, SocketFlags flags,
  744. ref EndPoint remote_end) {
  745. return(ReceiveFrom(buf, 0, buf.Length, flags,
  746. ref remote_end));
  747. }
  748. public int ReceiveFrom(byte[] buf, int size, SocketFlags flags,
  749. ref EndPoint remote_end) {
  750. return(ReceiveFrom(buf, 0, size, flags,
  751. ref remote_end));
  752. }
  753. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  754. private extern static int RecvFrom_internal(IntPtr sock,
  755. byte[] buffer,
  756. int offset,
  757. int count,
  758. SocketFlags flags,
  759. ref SocketAddress sockaddr);
  760. public int ReceiveFrom(byte[] buf, int offset, int size,
  761. SocketFlags flags,
  762. ref EndPoint remote_end) {
  763. if(buf==null) {
  764. throw new ArgumentNullException("buffer is null");
  765. }
  766. if(remote_end==null) {
  767. throw new ArgumentNullException("remote endpoint is null");
  768. }
  769. if(offset<0 || offset>buf.Length) {
  770. throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
  771. }
  772. if(size<0 || offset+size>buf.Length) {
  773. throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
  774. }
  775. SocketAddress sockaddr=remote_end.Serialize();
  776. int count;
  777. try {
  778. count=RecvFrom_internal(socket, buf, offset,
  779. size, flags,
  780. ref sockaddr);
  781. } catch(SocketException) {
  782. connected=false;
  783. throw;
  784. }
  785. connected=true;
  786. // Stupidly, EndPoint.Create() is an
  787. // instance method
  788. remote_end=remote_end.Create(sockaddr);
  789. return(count);
  790. }
  791. public int Send(byte[] buf) {
  792. return(Send(buf, 0, buf.Length, SocketFlags.None));
  793. }
  794. public int Send(byte[] buf, SocketFlags flags) {
  795. return(Send(buf, 0, buf.Length, flags));
  796. }
  797. public int Send(byte[] buf, int size, SocketFlags flags) {
  798. return(Send(buf, 0, size, flags));
  799. }
  800. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  801. private extern static int Send_internal(IntPtr sock,
  802. byte[] buf, int offset,
  803. int count,
  804. SocketFlags flags);
  805. public int Send (byte[] buf, int offset, int size, SocketFlags flags)
  806. {
  807. if (buf == null)
  808. throw new ArgumentNullException ("buffer");
  809. if (offset < 0 || offset > buf.Length)
  810. throw new ArgumentOutOfRangeException ("offset");
  811. if (size < 0 || offset + size > buf.Length)
  812. throw new ArgumentOutOfRangeException ("size");
  813. if (size == 0)
  814. return 0;
  815. int ret;
  816. try {
  817. ret = Send_internal (socket, buf, offset, size, flags);
  818. } catch (SocketException) {
  819. connected = false;
  820. throw;
  821. }
  822. connected = true;
  823. return ret;
  824. }
  825. public int SendTo(byte[] buffer, EndPoint remote_end) {
  826. return(SendTo(buffer, 0, buffer.Length,
  827. SocketFlags.None, remote_end));
  828. }
  829. public int SendTo(byte[] buffer, SocketFlags flags,
  830. EndPoint remote_end) {
  831. return(SendTo(buffer, 0, buffer.Length, flags,
  832. remote_end));
  833. }
  834. public int SendTo(byte[] buffer, int size, SocketFlags flags,
  835. EndPoint remote_end) {
  836. return(SendTo(buffer, 0, size, flags, remote_end));
  837. }
  838. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  839. private extern static int SendTo_internal(IntPtr sock,
  840. byte[] buffer,
  841. int offset,
  842. int count,
  843. SocketFlags flags,
  844. SocketAddress sa);
  845. public int SendTo(byte[] buffer, int offset, int size,
  846. SocketFlags flags, EndPoint remote_end) {
  847. if(buffer==null) {
  848. throw new ArgumentNullException("buffer is null");
  849. }
  850. if(remote_end==null) {
  851. throw new ArgumentNullException("remote endpoint is null");
  852. }
  853. if(offset<0 || offset>buffer.Length) {
  854. throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
  855. }
  856. if(size<0 || offset+size>buffer.Length) {
  857. throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
  858. }
  859. SocketAddress sockaddr=remote_end.Serialize();
  860. int ret;
  861. try {
  862. ret=SendTo_internal(socket, buffer, offset,
  863. size, flags, sockaddr);
  864. }
  865. catch(SocketException) {
  866. connected=false;
  867. throw;
  868. }
  869. connected=true;
  870. return(ret);
  871. }
  872. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  873. private extern static void SetSocketOption_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, object obj_val, byte[] byte_val, int int_val);
  874. public void SetSocketOption(SocketOptionLevel level,
  875. SocketOptionName name,
  876. byte[] opt_value) {
  877. SetSocketOption_internal(socket, level, name, null,
  878. opt_value, 0);
  879. }
  880. public void SetSocketOption(SocketOptionLevel level,
  881. SocketOptionName name,
  882. int opt_value) {
  883. SetSocketOption_internal(socket, level, name, null,
  884. null, opt_value);
  885. }
  886. public void SetSocketOption(SocketOptionLevel level,
  887. SocketOptionName name,
  888. object opt_value) {
  889. if(opt_value==null) {
  890. throw new ArgumentNullException();
  891. }
  892. /* Passing a bool as the third parameter to
  893. * SetSocketOption causes this overload to be
  894. * used when in fact we want to pass the value
  895. * to the runtime as an int.
  896. */
  897. if(opt_value is System.Boolean) {
  898. bool bool_val=(bool)opt_value;
  899. /* Stupid casting rules :-( */
  900. if(bool_val==true) {
  901. SetSocketOption_internal(socket, level,
  902. name, null,
  903. null, 1);
  904. } else {
  905. SetSocketOption_internal(socket, level,
  906. name, null,
  907. null, 0);
  908. }
  909. } else {
  910. SetSocketOption_internal(socket, level, name,
  911. opt_value, null, 0);
  912. }
  913. }
  914. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  915. private extern static void Shutdown_internal(IntPtr socket, SocketShutdown how);
  916. public void Shutdown(SocketShutdown how) {
  917. Shutdown_internal(socket, how);
  918. }
  919. public override int GetHashCode ()
  920. {
  921. return (int) socket;
  922. }
  923. private bool disposed = false;
  924. protected virtual void Dispose(bool explicitDisposing) {
  925. // Check to see if Dispose has already been called
  926. if(!this.disposed) {
  927. // If this is a call to Dispose,
  928. // dispose all managed resources.
  929. if(explicitDisposing) {
  930. // Free up stuff here
  931. }
  932. // Release unmanaged resources
  933. this.disposed=true;
  934. connected=false;
  935. Close_internal(socket);
  936. }
  937. }
  938. public void Dispose() {
  939. Dispose(true);
  940. // Take yourself off the Finalization queue
  941. GC.SuppressFinalize(this);
  942. }
  943. ~Socket () {
  944. Dispose(false);
  945. }
  946. }
  947. }