Socket.cs 50 KB

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