Socket.cs 25 KB

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