Socket.cs 25 KB

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