Socket.cs 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818
  1. // System.Net.Sockets.Socket.cs
  2. //
  3. // Authors:
  4. // Phillip Pearson ([email protected])
  5. // Dick Porter <[email protected]>
  6. // Gonzalo Paniagua Javier ([email protected])
  7. //
  8. // Copyright (C) 2001, 2002 Phillip Pearson and Ximian, Inc.
  9. // http://www.myelin.co.nz
  10. // (c) 2004 Novell, Inc. (http://www.novell.com)
  11. //
  12. //
  13. // Permission is hereby granted, free of charge, to any person obtaining
  14. // a copy of this software and associated documentation files (the
  15. // "Software"), to deal in the Software without restriction, including
  16. // without limitation the rights to use, copy, modify, merge, publish,
  17. // distribute, sublicense, and/or sell copies of the Software, and to
  18. // permit persons to whom the Software is furnished to do so, subject to
  19. // the following conditions:
  20. //
  21. // The above copyright notice and this permission notice shall be
  22. // included in all copies or substantial portions of the Software.
  23. //
  24. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  25. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  26. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  27. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  28. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  29. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  30. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  31. //
  32. using System;
  33. using System.Net;
  34. using System.Collections;
  35. using System.Runtime.CompilerServices;
  36. using System.Runtime.InteropServices;
  37. using System.Threading;
  38. using System.Reflection;
  39. using System.IO;
  40. namespace System.Net.Sockets
  41. {
  42. public class Socket : IDisposable
  43. {
  44. enum SocketOperation {
  45. Accept,
  46. Connect,
  47. Receive,
  48. ReceiveFrom,
  49. Send,
  50. SendTo
  51. }
  52. [StructLayout (LayoutKind.Sequential)]
  53. private sealed class SocketAsyncResult: IAsyncResult
  54. {
  55. /* Same structure in the runtime */
  56. public Socket Sock;
  57. public IntPtr handle;
  58. object state;
  59. AsyncCallback callback;
  60. WaitHandle waithandle;
  61. Exception delayedException;
  62. public EndPoint EndPoint; // Connect,ReceiveFrom,SendTo
  63. public byte [] Buffer; // Receive,ReceiveFrom,Send,SendTo
  64. public int Offset; // Receive,ReceiveFrom,Send,SendTo
  65. public int Size; // Receive,ReceiveFrom,Send,SendTo
  66. public SocketFlags SockFlags; // Receive,ReceiveFrom,Send,SendTo
  67. // Return values
  68. Socket acc_socket;
  69. int total;
  70. bool completed_sync;
  71. bool completed;
  72. public bool blocking;
  73. internal int error;
  74. SocketOperation operation;
  75. public object ares;
  76. public SocketAsyncResult (Socket sock, object state, AsyncCallback callback, SocketOperation operation)
  77. {
  78. this.Sock = sock;
  79. this.blocking = sock.blocking;
  80. this.handle = sock.socket;
  81. this.state = state;
  82. this.callback = callback;
  83. this.operation = operation;
  84. SockFlags = SocketFlags.None;
  85. }
  86. public void CheckIfThrowDelayedException ()
  87. {
  88. if (delayedException != null)
  89. throw delayedException;
  90. if (error != 0) {
  91. throw new SocketException (error);
  92. }
  93. }
  94. void CompleteAllOnDispose (Queue queue)
  95. {
  96. object [] pending = queue.ToArray ();
  97. queue.Clear ();
  98. WaitCallback cb;
  99. for (int i = 0; i < pending.Length; i++) {
  100. SocketAsyncResult ares = (SocketAsyncResult) pending [i];
  101. cb = new WaitCallback (ares.CompleteDisposed);
  102. ThreadPool.QueueUserWorkItem (cb, null);
  103. }
  104. }
  105. void CompleteDisposed (object unused)
  106. {
  107. Complete ();
  108. }
  109. public void Complete ()
  110. {
  111. if (operation != SocketOperation.Receive && Sock.disposed)
  112. delayedException = new ObjectDisposedException (Sock.GetType ().ToString ());
  113. IsCompleted = true;
  114. Queue queue = null;
  115. if (operation == SocketOperation.Receive || operation == SocketOperation.ReceiveFrom) {
  116. queue = Sock.readQ;
  117. } else if (operation == SocketOperation.Send || operation == SocketOperation.SendTo) {
  118. queue = Sock.writeQ;
  119. }
  120. if (queue != null) {
  121. SocketAsyncCall sac = null;
  122. SocketAsyncResult req = null;
  123. lock (queue) {
  124. queue.Dequeue (); // remove ourselves
  125. if (queue.Count > 0) {
  126. req = (SocketAsyncResult) queue.Peek ();
  127. if (!Sock.disposed) {
  128. Worker worker = new Worker (req);
  129. sac = GetDelegate (worker, req.operation);
  130. } else {
  131. CompleteAllOnDispose (queue);
  132. }
  133. }
  134. }
  135. if (sac != null)
  136. sac.BeginInvoke (null, req);
  137. }
  138. if (callback != null)
  139. callback (this);
  140. }
  141. SocketAsyncCall GetDelegate (Worker worker, SocketOperation op)
  142. {
  143. switch (op) {
  144. case SocketOperation.Receive:
  145. return new SocketAsyncCall (worker.Receive);
  146. case SocketOperation.ReceiveFrom:
  147. return new SocketAsyncCall (worker.ReceiveFrom);
  148. case SocketOperation.Send:
  149. return new SocketAsyncCall (worker.Send);
  150. case SocketOperation.SendTo:
  151. return new SocketAsyncCall (worker.SendTo);
  152. default:
  153. return null; // never happens
  154. }
  155. }
  156. public void Complete (bool synch)
  157. {
  158. completed_sync = synch;
  159. Complete ();
  160. }
  161. public void Complete (int total)
  162. {
  163. this.total = total;
  164. Complete ();
  165. }
  166. public void Complete (Exception e, bool synch)
  167. {
  168. completed_sync = synch;
  169. delayedException = e;
  170. Complete ();
  171. }
  172. public void Complete (Exception e)
  173. {
  174. delayedException = e;
  175. Complete ();
  176. }
  177. public void Complete (Socket s)
  178. {
  179. acc_socket = s;
  180. Complete ();
  181. }
  182. public object AsyncState {
  183. get {
  184. return state;
  185. }
  186. }
  187. public WaitHandle AsyncWaitHandle {
  188. get {
  189. lock (this) {
  190. if (waithandle == null)
  191. waithandle = new ManualResetEvent (completed);
  192. }
  193. return waithandle;
  194. }
  195. set {
  196. waithandle=value;
  197. }
  198. }
  199. public bool CompletedSynchronously {
  200. get {
  201. return(completed_sync);
  202. }
  203. }
  204. public bool IsCompleted {
  205. get {
  206. return(completed);
  207. }
  208. set {
  209. completed=value;
  210. lock (this) {
  211. if (waithandle != null && value) {
  212. ((ManualResetEvent) waithandle).Set ();
  213. }
  214. }
  215. }
  216. }
  217. public Socket Socket {
  218. get {
  219. return acc_socket;
  220. }
  221. }
  222. public int Total {
  223. get { return total; }
  224. set { total = value; }
  225. }
  226. }
  227. private sealed class Worker
  228. {
  229. SocketAsyncResult result;
  230. public Worker (SocketAsyncResult ares)
  231. {
  232. this.result = ares;
  233. }
  234. public void Accept ()
  235. {
  236. Socket acc_socket = null;
  237. try {
  238. acc_socket = result.Sock.Accept ();
  239. } catch (Exception e) {
  240. result.Complete (e);
  241. return;
  242. }
  243. result.Complete (acc_socket);
  244. }
  245. public void Connect ()
  246. {
  247. try {
  248. if (!result.Sock.Blocking) {
  249. result.Sock.Poll (-1, SelectMode.SelectWrite);
  250. int success = (int)result.Sock.GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
  251. if (success == 0) {
  252. result.Sock.connected = true;
  253. } else {
  254. result.Complete (new SocketException (success));
  255. return;
  256. }
  257. } else {
  258. result.Sock.Connect (result.EndPoint);
  259. result.Sock.connected = true;
  260. }
  261. } catch (Exception e) {
  262. result.Complete (e);
  263. return;
  264. }
  265. result.Complete ();
  266. }
  267. public void Receive ()
  268. {
  269. // Actual recv() done in the runtime
  270. result.Complete ();
  271. }
  272. public void ReceiveFrom ()
  273. {
  274. int total = 0;
  275. try {
  276. total = result.Sock.ReceiveFrom_nochecks (result.Buffer,
  277. result.Offset,
  278. result.Size,
  279. result.SockFlags,
  280. ref result.EndPoint);
  281. } catch (Exception e) {
  282. result.Complete (e);
  283. return;
  284. }
  285. result.Complete (total);
  286. }
  287. int send_so_far;
  288. void UpdateSendValues (int last_sent)
  289. {
  290. if (result.error == 0) {
  291. send_so_far += last_sent;
  292. result.Offset += last_sent;
  293. result.Size -= last_sent;
  294. }
  295. }
  296. public void Send ()
  297. {
  298. // Actual send() done in the runtime
  299. if (result.error == 0) {
  300. UpdateSendValues (result.Total);
  301. if (result.Sock.disposed) {
  302. result.Complete ();
  303. return;
  304. }
  305. if (result.Size > 0) {
  306. SocketAsyncCall sac = new SocketAsyncCall (this.Send);
  307. sac.BeginInvoke (null, result);
  308. return; // Have to finish writing everything. See bug #74475.
  309. }
  310. result.Total = send_so_far;
  311. }
  312. result.Complete ();
  313. }
  314. public void SendTo ()
  315. {
  316. int total = 0;
  317. try {
  318. total = result.Sock.SendTo_nochecks (result.Buffer,
  319. result.Offset,
  320. result.Size,
  321. result.SockFlags,
  322. result.EndPoint);
  323. UpdateSendValues (total);
  324. if (result.Size > 0) {
  325. SocketAsyncCall sac = new SocketAsyncCall (this.SendTo);
  326. sac.BeginInvoke (null, result);
  327. return; // Have to finish writing everything. See bug #74475.
  328. }
  329. result.Total = send_so_far;
  330. } catch (Exception e) {
  331. result.Complete (e);
  332. return;
  333. }
  334. result.Complete ();
  335. }
  336. }
  337. /* the field "socket" is looked up by name by the runtime */
  338. private IntPtr socket;
  339. private AddressFamily address_family;
  340. private SocketType socket_type;
  341. private ProtocolType protocol_type;
  342. internal bool blocking=true;
  343. private Queue readQ = new Queue (2);
  344. private Queue writeQ = new Queue (2);
  345. delegate void SocketAsyncCall ();
  346. /*
  347. * These two fields are looked up by name by the runtime, don't change
  348. * their name without also updating the runtime code.
  349. */
  350. private static int ipv4Supported = -1, ipv6Supported = -1;
  351. /* When true, the socket was connected at the time of
  352. * the last IO operation
  353. */
  354. private bool connected=false;
  355. /* true if we called Close_internal */
  356. private bool closed;
  357. internal bool disposed;
  358. /* Used in LocalEndPoint and RemoteEndPoint if the
  359. * Mono.Posix assembly is available
  360. */
  361. private static object unixendpoint=null;
  362. private static Type unixendpointtype=null;
  363. static void AddSockets (ArrayList sockets, IList list, string name)
  364. {
  365. if (list != null) {
  366. foreach (Socket sock in list) {
  367. if (sock == null) // MS throws a NullRef
  368. throw new ArgumentNullException (name, "Contains a null element");
  369. sockets.Add (sock);
  370. }
  371. }
  372. sockets.Add (null);
  373. }
  374. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  375. private extern static void Select_internal (ref Socket [] sockets,
  376. int microSeconds,
  377. out int error);
  378. public static void Select (IList checkRead, IList checkWrite, IList checkError, int microSeconds)
  379. {
  380. ArrayList list = new ArrayList ();
  381. AddSockets (list, checkRead, "checkRead");
  382. AddSockets (list, checkWrite, "checkWrite");
  383. AddSockets (list, checkError, "checkError");
  384. if (list.Count == 3) {
  385. throw new ArgumentNullException ("checkRead, checkWrite, checkError",
  386. "All the lists are null or empty.");
  387. }
  388. int error;
  389. /*
  390. * The 'sockets' array contains: READ socket 0-n, null,
  391. * WRITE socket 0-n, null,
  392. * ERROR socket 0-n, null
  393. */
  394. Socket [] sockets = (Socket []) list.ToArray (typeof (Socket));
  395. Select_internal (ref sockets, microSeconds, out error);
  396. if (error != 0)
  397. throw new SocketException (error);
  398. if (checkRead != null)
  399. checkRead.Clear ();
  400. if (checkWrite != null)
  401. checkWrite.Clear ();
  402. if (checkError != null)
  403. checkError.Clear ();
  404. if (sockets == null)
  405. return;
  406. int mode = 0;
  407. int count = sockets.Length;
  408. IList currentList = checkRead;
  409. for (int i = 0; i < count; i++) {
  410. Socket sock = sockets [i];
  411. if (sock == null) { // separator
  412. currentList = (mode == 0) ? checkWrite : checkError;
  413. mode++;
  414. continue;
  415. }
  416. if (currentList != null) {
  417. sock.connected = true;
  418. currentList.Add (sock);
  419. }
  420. }
  421. }
  422. static Socket() {
  423. Assembly ass;
  424. try {
  425. ass = Assembly.Load (Consts.AssemblyMono_Posix);
  426. } catch (FileNotFoundException) {
  427. return;
  428. }
  429. unixendpointtype=ass.GetType("Mono.Posix.UnixEndPoint");
  430. /* The endpoint Create() method is an instance
  431. * method :-(
  432. */
  433. Type[] arg_types=new Type[1];
  434. arg_types[0]=typeof(string);
  435. ConstructorInfo cons=unixendpointtype.GetConstructor(arg_types);
  436. object[] args=new object[1];
  437. args[0]="";
  438. unixendpoint=cons.Invoke(args);
  439. }
  440. // private constructor used by Accept, which already
  441. // has a socket handle to use
  442. private Socket(AddressFamily family, SocketType type,
  443. ProtocolType proto, IntPtr sock) {
  444. address_family=family;
  445. socket_type=type;
  446. protocol_type=proto;
  447. socket=sock;
  448. connected=true;
  449. }
  450. // Creates a new system socket, returning the handle
  451. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  452. private extern IntPtr Socket_internal(AddressFamily family,
  453. SocketType type,
  454. ProtocolType proto,
  455. out int error);
  456. public Socket(AddressFamily family, SocketType type,
  457. ProtocolType proto) {
  458. address_family=family;
  459. socket_type=type;
  460. protocol_type=proto;
  461. int error;
  462. socket=Socket_internal(family, type, proto, out error);
  463. if (error != 0) {
  464. throw new SocketException (error);
  465. }
  466. }
  467. public AddressFamily AddressFamily {
  468. get {
  469. return(address_family);
  470. }
  471. }
  472. // Returns the amount of data waiting to be read on socket
  473. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  474. private extern static int Available_internal(IntPtr socket,
  475. out int error);
  476. public int Available {
  477. get {
  478. if (disposed && closed)
  479. throw new ObjectDisposedException (GetType ().ToString ());
  480. int ret, error;
  481. ret = Available_internal(socket, out error);
  482. if (error != 0) {
  483. throw new SocketException (error);
  484. }
  485. return(ret);
  486. }
  487. }
  488. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  489. private extern static void Blocking_internal(IntPtr socket,
  490. bool block,
  491. out int error);
  492. public bool Blocking {
  493. get {
  494. return(blocking);
  495. }
  496. set {
  497. if (disposed && closed)
  498. throw new ObjectDisposedException (GetType ().ToString ());
  499. int error;
  500. Blocking_internal(socket, value, out error);
  501. if (error != 0) {
  502. throw new SocketException (error);
  503. }
  504. blocking=value;
  505. }
  506. }
  507. public bool Connected {
  508. get {
  509. return(connected);
  510. }
  511. }
  512. public IntPtr Handle {
  513. get {
  514. return(socket);
  515. }
  516. }
  517. // Returns the local endpoint details in addr and port
  518. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  519. private extern static SocketAddress LocalEndPoint_internal(IntPtr socket, out int error);
  520. [MonoTODO("Support non-IP endpoints")]
  521. public EndPoint LocalEndPoint {
  522. get {
  523. if (disposed && closed)
  524. throw new ObjectDisposedException (GetType ().ToString ());
  525. SocketAddress sa;
  526. int error;
  527. sa=LocalEndPoint_internal(socket, out error);
  528. if (error != 0) {
  529. throw new SocketException (error);
  530. }
  531. if(sa.Family==AddressFamily.InterNetwork || sa.Family==AddressFamily.InterNetworkV6) {
  532. // Stupidly, EndPoint.Create() is an
  533. // instance method
  534. return new IPEndPoint(0, 0).Create(sa);
  535. } else if (sa.Family==AddressFamily.Unix &&
  536. unixendpoint!=null) {
  537. return((EndPoint)unixendpointtype.InvokeMember("Create", BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public, null, unixendpoint, new object[] {sa}));
  538. } else {
  539. throw new NotImplementedException();
  540. }
  541. }
  542. }
  543. public ProtocolType ProtocolType {
  544. get {
  545. return(protocol_type);
  546. }
  547. }
  548. // Returns the remote endpoint details in addr and port
  549. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  550. private extern static SocketAddress RemoteEndPoint_internal(IntPtr socket, out int error);
  551. [MonoTODO("Support non-IP endpoints")]
  552. public EndPoint RemoteEndPoint {
  553. get {
  554. if (disposed && closed)
  555. throw new ObjectDisposedException (GetType ().ToString ());
  556. SocketAddress sa;
  557. int error;
  558. sa=RemoteEndPoint_internal(socket, out error);
  559. if (error != 0) {
  560. throw new SocketException (error);
  561. }
  562. if(sa.Family==AddressFamily.InterNetwork || sa.Family==AddressFamily.InterNetworkV6 ) {
  563. // Stupidly, EndPoint.Create() is an
  564. // instance method
  565. return new IPEndPoint(0, 0).Create(sa);
  566. } else if (sa.Family==AddressFamily.Unix &&
  567. unixendpoint!=null) {
  568. return((EndPoint)unixendpointtype.InvokeMember("Create", BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public, null, unixendpoint, new object[] {sa}));
  569. } else {
  570. throw new NotImplementedException();
  571. }
  572. }
  573. }
  574. public SocketType SocketType {
  575. get {
  576. return(socket_type);
  577. }
  578. }
  579. #if NET_1_1
  580. public static bool SupportsIPv4 {
  581. get {
  582. CheckProtocolSupport();
  583. return ipv4Supported == 1;
  584. }
  585. }
  586. public static bool SupportsIPv6 {
  587. get {
  588. CheckProtocolSupport();
  589. return ipv6Supported == 1;
  590. }
  591. }
  592. #else
  593. internal static bool SupportsIPv4
  594. {
  595. get
  596. {
  597. return true;
  598. }
  599. }
  600. internal static bool SupportsIPv6
  601. {
  602. get
  603. {
  604. return false;
  605. }
  606. }
  607. #endif
  608. internal static void CheckProtocolSupport()
  609. {
  610. if(ipv4Supported == -1) {
  611. try {
  612. Socket tmp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  613. tmp.Close();
  614. ipv4Supported = 1;
  615. }
  616. catch {
  617. ipv4Supported = 0;
  618. }
  619. }
  620. if(ipv6Supported == -1) {
  621. NetConfig config = (NetConfig)System.Configuration.ConfigurationSettings.GetConfig("system.net/settings");
  622. if(config != null)
  623. ipv6Supported = config.ipv6Enabled?-1:0;
  624. if(ipv6Supported != 0) {
  625. try {
  626. Socket tmp = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
  627. tmp.Close();
  628. ipv6Supported = 1;
  629. }
  630. catch { }
  631. }
  632. }
  633. }
  634. // Creates a new system socket, returning the handle
  635. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  636. private extern static IntPtr Accept_internal(IntPtr sock,
  637. out int error);
  638. Thread blocking_thread;
  639. public Socket Accept() {
  640. if (disposed && closed)
  641. throw new ObjectDisposedException (GetType ().ToString ());
  642. int error = 0;
  643. IntPtr sock = (IntPtr) (-1);
  644. blocking_thread = Thread.CurrentThread;
  645. try {
  646. sock = Accept_internal(socket, out error);
  647. } catch (ThreadAbortException the) {
  648. if (disposed) {
  649. Thread.ResetAbort ();
  650. error = 10004;
  651. }
  652. } finally {
  653. blocking_thread = null;
  654. }
  655. if (error != 0) {
  656. throw new SocketException (error);
  657. }
  658. Socket accepted = new Socket(this.AddressFamily,
  659. this.SocketType,
  660. this.ProtocolType, sock);
  661. accepted.Blocking = this.Blocking;
  662. return(accepted);
  663. }
  664. public IAsyncResult BeginAccept(AsyncCallback callback,
  665. object state) {
  666. if (disposed && closed)
  667. throw new ObjectDisposedException (GetType ().ToString ());
  668. SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Accept);
  669. Worker worker = new Worker (req);
  670. SocketAsyncCall sac = new SocketAsyncCall (worker.Accept);
  671. sac.BeginInvoke (null, req);
  672. return(req);
  673. }
  674. public IAsyncResult BeginConnect(EndPoint end_point,
  675. AsyncCallback callback,
  676. object state) {
  677. if (disposed && closed)
  678. throw new ObjectDisposedException (GetType ().ToString ());
  679. if (end_point == null)
  680. throw new ArgumentNullException ("end_point");
  681. SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Connect);
  682. req.EndPoint = end_point;
  683. // Bug #75154: Connect() should not succeed for .Any addresses.
  684. if (end_point is IPEndPoint) {
  685. IPEndPoint ep = (IPEndPoint) end_point;
  686. if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)) {
  687. req.Complete (new SocketException (10049), true);
  688. return req;
  689. }
  690. }
  691. int error = 0;
  692. if (!blocking) {
  693. SocketAddress serial = end_point.Serialize ();
  694. Connect_internal (socket, serial, out error);
  695. if (error == 0) {
  696. // succeeded synch
  697. connected = true;
  698. req.Complete (true);
  699. } else if (error != 10036 && error != 10035) {
  700. // error synch
  701. connected = false;
  702. req.Complete (new SocketException (error), true);
  703. }
  704. }
  705. if (blocking || error == 10036 || error == 10035) {
  706. // continue asynch
  707. connected = false;
  708. Worker worker = new Worker (req);
  709. SocketAsyncCall sac = new SocketAsyncCall (worker.Connect);
  710. sac.BeginInvoke (null, req);
  711. }
  712. return(req);
  713. }
  714. public IAsyncResult BeginReceive(byte[] buffer, int offset,
  715. int size,
  716. SocketFlags socket_flags,
  717. AsyncCallback callback,
  718. object state) {
  719. if (disposed && closed)
  720. throw new ObjectDisposedException (GetType ().ToString ());
  721. if (buffer == null)
  722. throw new ArgumentNullException ("buffer");
  723. if (offset < 0 || offset > buffer.Length)
  724. throw new ArgumentOutOfRangeException ("offset");
  725. if (size < 0 || offset + size > buffer.Length)
  726. throw new ArgumentOutOfRangeException ("size");
  727. SocketAsyncResult req;
  728. lock (readQ) {
  729. req = new SocketAsyncResult (this, state, callback, SocketOperation.Receive);
  730. req.Buffer = buffer;
  731. req.Offset = offset;
  732. req.Size = size;
  733. req.SockFlags = socket_flags;
  734. readQ.Enqueue (req);
  735. if (readQ.Count == 1) {
  736. Worker worker = new Worker (req);
  737. SocketAsyncCall sac = new SocketAsyncCall (worker.Receive);
  738. sac.BeginInvoke (null, req);
  739. }
  740. }
  741. return req;
  742. }
  743. public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset,
  744. int size,
  745. SocketFlags socket_flags,
  746. ref EndPoint remote_end,
  747. AsyncCallback callback,
  748. object state) {
  749. if (disposed && closed)
  750. throw new ObjectDisposedException (GetType ().ToString ());
  751. if (buffer == null)
  752. throw new ArgumentNullException ("buffer");
  753. if (offset < 0)
  754. throw new ArgumentOutOfRangeException ("offset must be >= 0");
  755. if (size < 0)
  756. throw new ArgumentOutOfRangeException ("size must be >= 0");
  757. if (offset + size > buffer.Length)
  758. throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
  759. SocketAsyncResult req;
  760. lock (readQ) {
  761. req = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveFrom);
  762. req.Buffer = buffer;
  763. req.Offset = offset;
  764. req.Size = size;
  765. req.SockFlags = socket_flags;
  766. req.EndPoint = remote_end;
  767. readQ.Enqueue (req);
  768. if (readQ.Count == 1) {
  769. Worker worker = new Worker (req);
  770. SocketAsyncCall sac = new SocketAsyncCall (worker.ReceiveFrom);
  771. sac.BeginInvoke (null, req);
  772. }
  773. }
  774. return req;
  775. }
  776. public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socket_flags,
  777. AsyncCallback callback, object state)
  778. {
  779. if (disposed && closed)
  780. throw new ObjectDisposedException (GetType ().ToString ());
  781. if (buffer == null)
  782. throw new ArgumentNullException ("buffer");
  783. if (offset < 0)
  784. throw new ArgumentOutOfRangeException ("offset must be >= 0");
  785. if (size < 0)
  786. throw new ArgumentOutOfRangeException ("size must be >= 0");
  787. if (offset + size > buffer.Length)
  788. throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
  789. SocketAsyncResult req;
  790. lock (writeQ) {
  791. req = new SocketAsyncResult (this, state, callback, SocketOperation.Send);
  792. req.Buffer = buffer;
  793. req.Offset = offset;
  794. req.Size = size;
  795. req.SockFlags = socket_flags;
  796. writeQ.Enqueue (req);
  797. if (writeQ.Count == 1) {
  798. Worker worker = new Worker (req);
  799. SocketAsyncCall sac = new SocketAsyncCall (worker.Send);
  800. sac.BeginInvoke (null, req);
  801. }
  802. }
  803. return req;
  804. }
  805. public IAsyncResult BeginSendTo(byte[] buffer, int offset,
  806. int size,
  807. SocketFlags socket_flags,
  808. EndPoint remote_end,
  809. AsyncCallback callback,
  810. object state) {
  811. if (disposed && closed)
  812. throw new ObjectDisposedException (GetType ().ToString ());
  813. if (buffer == null)
  814. throw new ArgumentNullException ("buffer");
  815. if (offset < 0)
  816. throw new ArgumentOutOfRangeException ("offset must be >= 0");
  817. if (size < 0)
  818. throw new ArgumentOutOfRangeException ("size must be >= 0");
  819. if (offset + size > buffer.Length)
  820. throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
  821. SocketAsyncResult req;
  822. lock (writeQ) {
  823. req = new SocketAsyncResult (this, state, callback, SocketOperation.SendTo);
  824. req.Buffer = buffer;
  825. req.Offset = offset;
  826. req.Size = size;
  827. req.SockFlags = socket_flags;
  828. req.EndPoint = remote_end;
  829. writeQ.Enqueue (req);
  830. if (writeQ.Count == 1) {
  831. Worker worker = new Worker (req);
  832. SocketAsyncCall sac = new SocketAsyncCall (worker.SendTo);
  833. sac.BeginInvoke (null, req);
  834. }
  835. }
  836. return req;
  837. }
  838. // Creates a new system socket, returning the handle
  839. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  840. private extern static void Bind_internal(IntPtr sock,
  841. SocketAddress sa,
  842. out int error);
  843. public void Bind(EndPoint local_end) {
  844. if (disposed && closed)
  845. throw new ObjectDisposedException (GetType ().ToString ());
  846. if(local_end==null) {
  847. throw new ArgumentNullException("local_end");
  848. }
  849. int error;
  850. Bind_internal(socket, local_end.Serialize(),
  851. out error);
  852. if (error != 0) {
  853. throw new SocketException (error);
  854. }
  855. }
  856. // Closes the socket
  857. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  858. private extern static void Close_internal(IntPtr socket,
  859. out int error);
  860. public void Close() {
  861. ((IDisposable) this).Dispose ();
  862. }
  863. // Connects to the remote address
  864. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  865. private extern static void Connect_internal(IntPtr sock,
  866. SocketAddress sa,
  867. out int error);
  868. public void Connect(EndPoint remote_end) {
  869. if (disposed && closed)
  870. throw new ObjectDisposedException (GetType ().ToString ());
  871. if(remote_end==null) {
  872. throw new ArgumentNullException("remote_end");
  873. }
  874. if (remote_end is IPEndPoint) {
  875. IPEndPoint ep = (IPEndPoint) remote_end;
  876. if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any))
  877. throw new SocketException (10049);
  878. }
  879. SocketAddress serial = remote_end.Serialize ();
  880. int error = 0;
  881. blocking_thread = Thread.CurrentThread;
  882. try {
  883. Connect_internal (socket, serial, out error);
  884. } catch (ThreadAbortException the) {
  885. if (disposed) {
  886. Thread.ResetAbort ();
  887. error = 10004;
  888. }
  889. } finally {
  890. blocking_thread = null;
  891. }
  892. if (error != 0) {
  893. throw new SocketException (error);
  894. }
  895. connected=true;
  896. }
  897. public Socket EndAccept(IAsyncResult result) {
  898. if (disposed && closed)
  899. throw new ObjectDisposedException (GetType ().ToString ());
  900. if (result == null)
  901. throw new ArgumentNullException ("result");
  902. SocketAsyncResult req = result as SocketAsyncResult;
  903. if (req == null)
  904. throw new ArgumentException ("Invalid IAsyncResult", "result");
  905. if (!result.IsCompleted)
  906. result.AsyncWaitHandle.WaitOne();
  907. req.CheckIfThrowDelayedException();
  908. return req.Socket;
  909. }
  910. public void EndConnect(IAsyncResult result) {
  911. if (disposed && closed)
  912. throw new ObjectDisposedException (GetType ().ToString ());
  913. if (result == null)
  914. throw new ArgumentNullException ("result");
  915. SocketAsyncResult req = result as SocketAsyncResult;
  916. if (req == null)
  917. throw new ArgumentException ("Invalid IAsyncResult", "result");
  918. if (!result.IsCompleted)
  919. result.AsyncWaitHandle.WaitOne();
  920. req.CheckIfThrowDelayedException();
  921. }
  922. public int EndReceive(IAsyncResult result) {
  923. if (disposed && closed)
  924. throw new ObjectDisposedException (GetType ().ToString ());
  925. if (result == null)
  926. throw new ArgumentNullException ("result");
  927. SocketAsyncResult req = result as SocketAsyncResult;
  928. if (req == null)
  929. throw new ArgumentException ("Invalid IAsyncResult", "result");
  930. if (!result.IsCompleted)
  931. result.AsyncWaitHandle.WaitOne();
  932. req.CheckIfThrowDelayedException();
  933. return req.Total;
  934. }
  935. public int EndReceiveFrom(IAsyncResult result,
  936. ref EndPoint end_point) {
  937. if (disposed && closed)
  938. throw new ObjectDisposedException (GetType ().ToString ());
  939. if (result == null)
  940. throw new ArgumentNullException ("result");
  941. SocketAsyncResult req = result as SocketAsyncResult;
  942. if (req == null)
  943. throw new ArgumentException ("Invalid IAsyncResult", "result");
  944. if (!result.IsCompleted)
  945. result.AsyncWaitHandle.WaitOne();
  946. req.CheckIfThrowDelayedException();
  947. end_point = req.EndPoint;
  948. return req.Total;
  949. }
  950. public int EndSend(IAsyncResult result) {
  951. if (disposed && closed)
  952. throw new ObjectDisposedException (GetType ().ToString ());
  953. if (result == null)
  954. throw new ArgumentNullException ("result");
  955. SocketAsyncResult req = result as SocketAsyncResult;
  956. if (req == null)
  957. throw new ArgumentException ("Invalid IAsyncResult", "result");
  958. if (!result.IsCompleted)
  959. result.AsyncWaitHandle.WaitOne();
  960. req.CheckIfThrowDelayedException();
  961. return req.Total;
  962. }
  963. public int EndSendTo(IAsyncResult result) {
  964. if (disposed && closed)
  965. throw new ObjectDisposedException (GetType ().ToString ());
  966. if (result == null)
  967. throw new ArgumentNullException ("result");
  968. SocketAsyncResult req = result as SocketAsyncResult;
  969. if (req == null)
  970. throw new ArgumentException ("Invalid IAsyncResult", "result");
  971. if (!result.IsCompleted)
  972. result.AsyncWaitHandle.WaitOne();
  973. req.CheckIfThrowDelayedException();
  974. return req.Total;
  975. }
  976. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  977. private extern static void GetSocketOption_obj_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, out object obj_val, out int error);
  978. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  979. private extern static void GetSocketOption_arr_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val, out int error);
  980. public object GetSocketOption (SocketOptionLevel level, SocketOptionName name)
  981. {
  982. if (disposed && closed)
  983. throw new ObjectDisposedException (GetType ().ToString ());
  984. object obj_val;
  985. int error;
  986. GetSocketOption_obj_internal(socket, level, name,
  987. out obj_val, out error);
  988. if (error != 0) {
  989. throw new SocketException (error);
  990. }
  991. if(name==SocketOptionName.Linger) {
  992. return((LingerOption)obj_val);
  993. } else if (name==SocketOptionName.AddMembership ||
  994. name==SocketOptionName.DropMembership) {
  995. return((MulticastOption)obj_val);
  996. } else if (obj_val is int) {
  997. return((int)obj_val);
  998. } else {
  999. return(obj_val);
  1000. }
  1001. }
  1002. public void GetSocketOption (SocketOptionLevel level, SocketOptionName name, byte [] opt_value)
  1003. {
  1004. if (disposed && closed)
  1005. throw new ObjectDisposedException (GetType ().ToString ());
  1006. int error;
  1007. GetSocketOption_arr_internal(socket, level, name,
  1008. ref opt_value, out error);
  1009. if (error != 0) {
  1010. throw new SocketException (error);
  1011. }
  1012. }
  1013. public byte [] GetSocketOption (SocketOptionLevel level, SocketOptionName name, int length)
  1014. {
  1015. if (disposed && closed)
  1016. throw new ObjectDisposedException (GetType ().ToString ());
  1017. byte[] byte_val=new byte[length];
  1018. int error;
  1019. GetSocketOption_arr_internal(socket, level, name,
  1020. ref byte_val, out error);
  1021. if (error != 0) {
  1022. throw new SocketException (error);
  1023. }
  1024. return(byte_val);
  1025. }
  1026. // See Socket.IOControl, WSAIoctl documentation in MSDN. The
  1027. // common options between UNIX and Winsock are FIONREAD,
  1028. // FIONBIO and SIOCATMARK. Anything else will depend on the
  1029. // system.
  1030. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1031. extern static int WSAIoctl (IntPtr sock, int ioctl_code,
  1032. byte [] input, byte [] output,
  1033. out int error);
  1034. public int IOControl (int ioctl_code, byte [] in_value, byte [] out_value)
  1035. {
  1036. if (disposed)
  1037. throw new ObjectDisposedException (GetType ().ToString ());
  1038. int error;
  1039. int result = WSAIoctl (socket, ioctl_code, in_value,
  1040. out_value, out error);
  1041. if (error != 0) {
  1042. throw new SocketException (error);
  1043. }
  1044. if (result == -1)
  1045. throw new InvalidOperationException ("Must use Blocking property instead.");
  1046. return result;
  1047. }
  1048. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1049. private extern static void Listen_internal(IntPtr sock,
  1050. int backlog,
  1051. out int error);
  1052. public void Listen (int backlog)
  1053. {
  1054. if (disposed && closed)
  1055. throw new ObjectDisposedException (GetType ().ToString ());
  1056. int error;
  1057. Listen_internal(socket, backlog, out error);
  1058. if (error != 0) {
  1059. throw new SocketException (error);
  1060. }
  1061. }
  1062. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1063. extern static bool Poll_internal (IntPtr socket, SelectMode mode, int timeout, out int error);
  1064. public bool Poll (int time_us, SelectMode mode)
  1065. {
  1066. if (disposed && closed)
  1067. throw new ObjectDisposedException (GetType ().ToString ());
  1068. if (mode != SelectMode.SelectRead &&
  1069. mode != SelectMode.SelectWrite &&
  1070. mode != SelectMode.SelectError)
  1071. throw new NotSupportedException ("'mode' parameter is not valid.");
  1072. int error;
  1073. bool result = Poll_internal (socket, mode, time_us, out error);
  1074. if (error != 0)
  1075. throw new SocketException (error);
  1076. if (result == true) {
  1077. /* Update the connected state; for
  1078. * non-blocking Connect()s this is
  1079. * when we can find out that the
  1080. * connect succeeded.
  1081. */
  1082. connected = true;
  1083. }
  1084. return result;
  1085. }
  1086. public int Receive (byte [] buf)
  1087. {
  1088. if (disposed && closed)
  1089. throw new ObjectDisposedException (GetType ().ToString ());
  1090. if (buf == null)
  1091. throw new ArgumentNullException ("buf");
  1092. return Receive_nochecks (buf, 0, buf.Length, SocketFlags.None);
  1093. }
  1094. public int Receive (byte [] buf, SocketFlags flags)
  1095. {
  1096. if (disposed && closed)
  1097. throw new ObjectDisposedException (GetType ().ToString ());
  1098. if (buf == null)
  1099. throw new ArgumentNullException ("buf");
  1100. return Receive_nochecks (buf, 0, buf.Length, flags);
  1101. }
  1102. public int Receive (byte [] buf, int size, SocketFlags flags)
  1103. {
  1104. if (disposed && closed)
  1105. throw new ObjectDisposedException (GetType ().ToString ());
  1106. if (buf == null)
  1107. throw new ArgumentNullException ("buf");
  1108. if (size < 0 || size > buf.Length)
  1109. throw new ArgumentOutOfRangeException ("size");
  1110. return Receive_nochecks (buf, 0, size, flags);
  1111. }
  1112. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1113. private extern static int Receive_internal(IntPtr sock,
  1114. byte[] buffer,
  1115. int offset,
  1116. int count,
  1117. SocketFlags flags,
  1118. out int error);
  1119. public int Receive (byte [] buf, int offset, int size, SocketFlags flags)
  1120. {
  1121. if (disposed && closed)
  1122. throw new ObjectDisposedException (GetType ().ToString ());
  1123. if (buf == null)
  1124. throw new ArgumentNullException ("buf");
  1125. if (offset < 0 || offset > buf.Length)
  1126. throw new ArgumentOutOfRangeException ("offset");
  1127. if (size < 0 || offset + size > buf.Length)
  1128. throw new ArgumentOutOfRangeException ("size");
  1129. return Receive_nochecks (buf, offset, size, flags);
  1130. }
  1131. int Receive_nochecks (byte [] buf, int offset, int size, SocketFlags flags)
  1132. {
  1133. int ret, error;
  1134. ret = Receive_internal (socket, buf, offset, size, flags, out error);
  1135. if (error != 0) {
  1136. if (error != 10035 && error != 10036) // WSAEWOULDBLOCK && WSAEINPROGRESS
  1137. connected = false;
  1138. throw new SocketException (error);
  1139. }
  1140. connected = true;
  1141. return ret;
  1142. }
  1143. public int ReceiveFrom (byte [] buf, ref EndPoint remote_end)
  1144. {
  1145. if (disposed && closed)
  1146. throw new ObjectDisposedException (GetType ().ToString ());
  1147. if (buf == null)
  1148. throw new ArgumentNullException ("buf");
  1149. if (remote_end == null)
  1150. throw new ArgumentNullException ("remote_end");
  1151. return ReceiveFrom_nochecks (buf, 0, buf.Length, SocketFlags.None, ref remote_end);
  1152. }
  1153. public int ReceiveFrom (byte [] buf, SocketFlags flags, ref EndPoint remote_end)
  1154. {
  1155. if (disposed && closed)
  1156. throw new ObjectDisposedException (GetType ().ToString ());
  1157. if (buf == null)
  1158. throw new ArgumentNullException ("buf");
  1159. if (remote_end == null)
  1160. throw new ArgumentNullException ("remote_end");
  1161. return ReceiveFrom_nochecks (buf, 0, buf.Length, flags, ref remote_end);
  1162. }
  1163. public int ReceiveFrom (byte [] buf, int size, SocketFlags flags,
  1164. ref EndPoint remote_end)
  1165. {
  1166. if (disposed && closed)
  1167. throw new ObjectDisposedException (GetType ().ToString ());
  1168. if (buf == null)
  1169. throw new ArgumentNullException ("buf");
  1170. if (remote_end == null)
  1171. throw new ArgumentNullException ("remote_end");
  1172. if (size < 0 || size > buf.Length)
  1173. throw new ArgumentOutOfRangeException ("size");
  1174. return ReceiveFrom_nochecks (buf, 0, size, flags, ref remote_end);
  1175. }
  1176. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1177. private extern static int RecvFrom_internal(IntPtr sock,
  1178. byte[] buffer,
  1179. int offset,
  1180. int count,
  1181. SocketFlags flags,
  1182. ref SocketAddress sockaddr,
  1183. out int error);
  1184. public int ReceiveFrom (byte [] buf, int offset, int size, SocketFlags flags,
  1185. ref EndPoint remote_end)
  1186. {
  1187. if (disposed && closed)
  1188. throw new ObjectDisposedException (GetType ().ToString ());
  1189. if (buf == null)
  1190. throw new ArgumentNullException ("buf");
  1191. if (remote_end == null)
  1192. throw new ArgumentNullException ("remote_end");
  1193. if (offset < 0 || offset > buf.Length)
  1194. throw new ArgumentOutOfRangeException ("offset");
  1195. if (size < 0 || offset + size > buf.Length)
  1196. throw new ArgumentOutOfRangeException ("size");
  1197. return ReceiveFrom_nochecks (buf, offset, size, flags, ref remote_end);
  1198. }
  1199. int ReceiveFrom_nochecks (byte [] buf, int offset, int size, SocketFlags flags,
  1200. ref EndPoint remote_end)
  1201. {
  1202. SocketAddress sockaddr = remote_end.Serialize();
  1203. int cnt, error;
  1204. cnt = RecvFrom_internal (socket, buf, offset, size, flags, ref sockaddr, out error);
  1205. if (error != 0) {
  1206. if (error != 10035 && error != 10036) // WSAEWOULDBLOCK && WSAEINPROGRESS
  1207. connected = false;
  1208. throw new SocketException (error);
  1209. }
  1210. connected = true;
  1211. // If sockaddr is null then we're a connection
  1212. // oriented protocol and should ignore the
  1213. // remote_end parameter (see MSDN
  1214. // documentation for Socket.ReceiveFrom(...) )
  1215. if ( sockaddr != null ) {
  1216. // Stupidly, EndPoint.Create() is an
  1217. // instance method
  1218. remote_end = remote_end.Create (sockaddr);
  1219. }
  1220. return cnt;
  1221. }
  1222. public int Send (byte [] buf)
  1223. {
  1224. if (disposed && closed)
  1225. throw new ObjectDisposedException (GetType ().ToString ());
  1226. if (buf == null)
  1227. throw new ArgumentNullException ("buf");
  1228. return Send_nochecks (buf, 0, buf.Length, SocketFlags.None);
  1229. }
  1230. public int Send (byte [] buf, SocketFlags flags)
  1231. {
  1232. if (disposed && closed)
  1233. throw new ObjectDisposedException (GetType ().ToString ());
  1234. if (buf == null)
  1235. throw new ArgumentNullException ("buf");
  1236. return Send_nochecks (buf, 0, buf.Length, flags);
  1237. }
  1238. public int Send (byte [] buf, int size, SocketFlags flags)
  1239. {
  1240. if (disposed && closed)
  1241. throw new ObjectDisposedException (GetType ().ToString ());
  1242. if (buf == null)
  1243. throw new ArgumentNullException ("buf");
  1244. if (size < 0 || size > buf.Length)
  1245. throw new ArgumentOutOfRangeException ("size");
  1246. return Send_nochecks (buf, 0, size, flags);
  1247. }
  1248. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1249. private extern static int Send_internal(IntPtr sock,
  1250. byte[] buf, int offset,
  1251. int count,
  1252. SocketFlags flags,
  1253. out int error);
  1254. public int Send (byte [] buf, int offset, int size, SocketFlags flags)
  1255. {
  1256. if (disposed && closed)
  1257. throw new ObjectDisposedException (GetType ().ToString ());
  1258. if (buf == null)
  1259. throw new ArgumentNullException ("buffer");
  1260. if (offset < 0 || offset > buf.Length)
  1261. throw new ArgumentOutOfRangeException ("offset");
  1262. if (size < 0 || offset + size > buf.Length)
  1263. throw new ArgumentOutOfRangeException ("size");
  1264. return Send_nochecks (buf, offset, size, flags);
  1265. }
  1266. int Send_nochecks (byte [] buf, int offset, int size, SocketFlags flags)
  1267. {
  1268. if (size == 0)
  1269. return 0;
  1270. int ret, error;
  1271. ret = Send_internal (socket, buf, offset, size, flags, out error);
  1272. if (error != 0) {
  1273. if (error != 10035 && error != 10036) // WSAEWOULDBLOCK && WSAEINPROGRESS
  1274. connected = false;
  1275. throw new SocketException (error);
  1276. }
  1277. connected = true;
  1278. return ret;
  1279. }
  1280. public int SendTo (byte [] buffer, EndPoint remote_end)
  1281. {
  1282. if (disposed && closed)
  1283. throw new ObjectDisposedException (GetType ().ToString ());
  1284. if (buffer == null)
  1285. throw new ArgumentNullException ("buffer");
  1286. if (remote_end == null)
  1287. throw new ArgumentNullException ("remote_end");
  1288. return SendTo_nochecks (buffer, 0, buffer.Length, SocketFlags.None, remote_end);
  1289. }
  1290. public int SendTo (byte [] buffer, SocketFlags flags, EndPoint remote_end)
  1291. {
  1292. if (disposed && closed)
  1293. throw new ObjectDisposedException (GetType ().ToString ());
  1294. if (buffer == null)
  1295. throw new ArgumentNullException ("buffer");
  1296. if (remote_end == null)
  1297. throw new ArgumentNullException ("remote_end");
  1298. return SendTo_nochecks (buffer, 0, buffer.Length, flags, remote_end);
  1299. }
  1300. public int SendTo (byte [] buffer, int size, SocketFlags flags, EndPoint remote_end)
  1301. {
  1302. if (disposed && closed)
  1303. throw new ObjectDisposedException (GetType ().ToString ());
  1304. if (buffer == null)
  1305. throw new ArgumentNullException ("buffer");
  1306. if (remote_end == null)
  1307. throw new ArgumentNullException ("remote_end");
  1308. if (size < 0 || size > buffer.Length)
  1309. throw new ArgumentOutOfRangeException ("size");
  1310. return SendTo_nochecks (buffer, 0, size, flags, remote_end);
  1311. }
  1312. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1313. private extern static int SendTo_internal(IntPtr sock,
  1314. byte[] buffer,
  1315. int offset,
  1316. int count,
  1317. SocketFlags flags,
  1318. SocketAddress sa,
  1319. out int error);
  1320. public int SendTo (byte [] buffer, int offset, int size, SocketFlags flags,
  1321. EndPoint remote_end)
  1322. {
  1323. if (disposed && closed)
  1324. throw new ObjectDisposedException (GetType ().ToString ());
  1325. if (buffer == null)
  1326. throw new ArgumentNullException ("buffer");
  1327. if (remote_end == null)
  1328. throw new ArgumentNullException("remote_end");
  1329. if (offset < 0 || offset > buffer.Length)
  1330. throw new ArgumentOutOfRangeException ("offset");
  1331. if (size < 0 || offset + size > buffer.Length)
  1332. throw new ArgumentOutOfRangeException ("size");
  1333. return SendTo_nochecks (buffer, offset, size, flags, remote_end);
  1334. }
  1335. int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags,
  1336. EndPoint remote_end)
  1337. {
  1338. SocketAddress sockaddr = remote_end.Serialize ();
  1339. int ret, error;
  1340. ret = SendTo_internal (socket, buffer, offset, size, flags, sockaddr, out error);
  1341. if (error != 0) {
  1342. if (error != 10035 && error != 10036) // WSAEWOULDBLOCK && WSAEINPROGRESS
  1343. connected = false;
  1344. throw new SocketException (error);
  1345. }
  1346. connected = true;
  1347. return ret;
  1348. }
  1349. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1350. private extern static void SetSocketOption_internal (IntPtr socket, SocketOptionLevel level,
  1351. SocketOptionName name, object obj_val,
  1352. byte [] byte_val, int int_val,
  1353. out int error);
  1354. public void SetSocketOption (SocketOptionLevel level, SocketOptionName name, byte[] opt_value)
  1355. {
  1356. if (disposed && closed)
  1357. throw new ObjectDisposedException (GetType ().ToString ());
  1358. int error;
  1359. SetSocketOption_internal(socket, level, name, null,
  1360. opt_value, 0, out error);
  1361. if (error != 0) {
  1362. throw new SocketException (error);
  1363. }
  1364. }
  1365. public void SetSocketOption (SocketOptionLevel level, SocketOptionName name, int opt_value)
  1366. {
  1367. if (disposed && closed)
  1368. throw new ObjectDisposedException (GetType ().ToString ());
  1369. int error;
  1370. SetSocketOption_internal(socket, level, name, null,
  1371. null, opt_value, out error);
  1372. if (error != 0) {
  1373. throw new SocketException (error);
  1374. }
  1375. }
  1376. public void SetSocketOption (SocketOptionLevel level, SocketOptionName name, object opt_value)
  1377. {
  1378. if (disposed && closed)
  1379. throw new ObjectDisposedException (GetType ().ToString ());
  1380. if(opt_value==null) {
  1381. throw new ArgumentNullException();
  1382. }
  1383. int error;
  1384. /* From MS documentation on SetSocketOption: "For an
  1385. * option with a Boolean data type, specify a nonzero
  1386. * value to enable the option, and a zero value to
  1387. * disable the option."
  1388. * Booleans are only handled in 2.0
  1389. */
  1390. if (opt_value is System.Boolean) {
  1391. #if NET_2_0
  1392. bool bool_val = (bool) opt_value;
  1393. int int_val = (bool_val) ? 1 : 0;
  1394. SetSocketOption_internal (socket, level, name, null, null, int_val, out error);
  1395. #else
  1396. throw new ArgumentException ("Use an integer 1 (true) or 0 (false) instead of a boolean.", "opt_value");
  1397. #endif
  1398. } else {
  1399. SetSocketOption_internal (socket, level, name, opt_value, null, 0, out error);
  1400. }
  1401. if (error != 0)
  1402. throw new SocketException (error);
  1403. }
  1404. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1405. private extern static void Shutdown_internal(IntPtr socket, SocketShutdown how, out int error);
  1406. public void Shutdown (SocketShutdown how)
  1407. {
  1408. if (disposed && closed)
  1409. throw new ObjectDisposedException (GetType ().ToString ());
  1410. int error;
  1411. Shutdown_internal(socket, how, out error);
  1412. if (error != 0) {
  1413. throw new SocketException (error);
  1414. }
  1415. }
  1416. public override int GetHashCode ()
  1417. {
  1418. return (int) socket;
  1419. }
  1420. protected virtual void Dispose (bool explicitDisposing)
  1421. {
  1422. if (disposed)
  1423. return;
  1424. disposed = true;
  1425. connected = false;
  1426. if ((int) socket != -1) {
  1427. int error;
  1428. closed = true;
  1429. IntPtr x = socket;
  1430. socket = (IntPtr) (-1);
  1431. Close_internal (x, out error);
  1432. if (blocking_thread != null) {
  1433. blocking_thread.Abort ();
  1434. blocking_thread = null;
  1435. }
  1436. if (error != 0)
  1437. throw new SocketException (error);
  1438. }
  1439. }
  1440. void IDisposable.Dispose ()
  1441. {
  1442. Dispose (true);
  1443. GC.SuppressFinalize (this);
  1444. }
  1445. ~Socket () {
  1446. Dispose(false);
  1447. }
  1448. }
  1449. }