Socket.cs 85 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281
  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. // Sridhar Kulkarni ([email protected])
  8. // Brian Nickel ([email protected])
  9. //
  10. // Copyright (C) 2001, 2002 Phillip Pearson and Ximian, Inc.
  11. // http://www.myelin.co.nz
  12. // (c) 2004-2006 Novell, Inc. (http://www.novell.com)
  13. //
  14. //
  15. // Permission is hereby granted, free of charge, to any person obtaining
  16. // a copy of this software and associated documentation files (the
  17. // "Software"), to deal in the Software without restriction, including
  18. // without limitation the rights to use, copy, modify, merge, publish,
  19. // distribute, sublicense, and/or sell copies of the Software, and to
  20. // permit persons to whom the Software is furnished to do so, subject to
  21. // the following conditions:
  22. //
  23. // The above copyright notice and this permission notice shall be
  24. // included in all copies or substantial portions of the Software.
  25. //
  26. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  27. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  28. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  29. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  30. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  31. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  32. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  33. //
  34. using System;
  35. using System.Net;
  36. using System.Collections;
  37. using System.Runtime.CompilerServices;
  38. using System.Runtime.InteropServices;
  39. using System.Threading;
  40. using System.Reflection;
  41. using System.IO;
  42. using System.Net.Configuration;
  43. using System.Text;
  44. #if NET_2_0
  45. using System.Collections.Generic;
  46. using System.Net.NetworkInformation;
  47. using System.Timers;
  48. #endif
  49. namespace System.Net.Sockets
  50. {
  51. public class Socket : IDisposable
  52. {
  53. enum SocketOperation {
  54. Accept,
  55. Connect,
  56. Receive,
  57. ReceiveFrom,
  58. Send,
  59. SendTo,
  60. UsedInManaged1,
  61. UsedInManaged2,
  62. UsedInProcess,
  63. UsedInConsole2,
  64. Disconnect,
  65. AcceptReceive
  66. }
  67. [StructLayout (LayoutKind.Sequential)]
  68. private sealed class SocketAsyncResult: IAsyncResult
  69. {
  70. /* Same structure in the runtime */
  71. public Socket Sock;
  72. public IntPtr handle;
  73. object state;
  74. AsyncCallback callback;
  75. WaitHandle waithandle;
  76. Exception delayedException;
  77. public EndPoint EndPoint; // Connect,ReceiveFrom,SendTo
  78. public byte [] Buffer; // Receive,ReceiveFrom,Send,SendTo
  79. public int Offset; // Receive,ReceiveFrom,Send,SendTo
  80. public int Size; // Receive,ReceiveFrom,Send,SendTo
  81. public SocketFlags SockFlags; // Receive,ReceiveFrom,Send,SendTo
  82. public Socket AcceptSocket; // AcceptReceive
  83. public IPAddress[] Addresses; // Connect
  84. public int Port; // Connect
  85. #if NET_2_0
  86. public IList<ArraySegment<byte>> Buffers; // Receive, Send
  87. #else
  88. public object Buffers; // Reserve this slot in older profiles
  89. #endif
  90. public bool ReuseSocket; // Disconnect
  91. // Return values
  92. Socket acc_socket;
  93. int total;
  94. bool completed_sync;
  95. bool completed;
  96. public bool blocking;
  97. internal int error;
  98. SocketOperation operation;
  99. public object ares;
  100. public SocketAsyncResult (Socket sock, object state, AsyncCallback callback, SocketOperation operation)
  101. {
  102. this.Sock = sock;
  103. this.blocking = sock.blocking;
  104. this.handle = sock.socket;
  105. this.state = state;
  106. this.callback = callback;
  107. this.operation = operation;
  108. SockFlags = SocketFlags.None;
  109. }
  110. public void CheckIfThrowDelayedException ()
  111. {
  112. if (delayedException != null) {
  113. throw delayedException;
  114. }
  115. if (error != 0)
  116. throw new SocketException (error);
  117. }
  118. void CompleteAllOnDispose (Queue queue)
  119. {
  120. object [] pending = queue.ToArray ();
  121. queue.Clear ();
  122. WaitCallback cb;
  123. for (int i = 0; i < pending.Length; i++) {
  124. SocketAsyncResult ares = (SocketAsyncResult) pending [i];
  125. cb = new WaitCallback (ares.CompleteDisposed);
  126. ThreadPool.QueueUserWorkItem (cb, null);
  127. }
  128. }
  129. void CompleteDisposed (object unused)
  130. {
  131. Complete ();
  132. }
  133. public void Complete ()
  134. {
  135. if (operation != SocketOperation.Receive && Sock.disposed)
  136. delayedException = new ObjectDisposedException (Sock.GetType ().ToString ());
  137. IsCompleted = true;
  138. Queue queue = null;
  139. if (operation == SocketOperation.Receive || operation == SocketOperation.ReceiveFrom) {
  140. queue = Sock.readQ;
  141. } else if (operation == SocketOperation.Send || operation == SocketOperation.SendTo) {
  142. queue = Sock.writeQ;
  143. }
  144. if (queue != null) {
  145. SocketAsyncCall sac = null;
  146. SocketAsyncResult req = null;
  147. lock (queue) {
  148. queue.Dequeue (); // remove ourselves
  149. if (queue.Count > 0) {
  150. req = (SocketAsyncResult) queue.Peek ();
  151. if (!Sock.disposed) {
  152. Worker worker = new Worker (req);
  153. sac = GetDelegate (worker, req.operation);
  154. } else {
  155. CompleteAllOnDispose (queue);
  156. }
  157. }
  158. }
  159. if (sac != null)
  160. sac.BeginInvoke (null, req);
  161. }
  162. if (callback != null)
  163. callback (this);
  164. }
  165. SocketAsyncCall GetDelegate (Worker worker, SocketOperation op)
  166. {
  167. switch (op) {
  168. case SocketOperation.Receive:
  169. return new SocketAsyncCall (worker.Receive);
  170. case SocketOperation.ReceiveFrom:
  171. return new SocketAsyncCall (worker.ReceiveFrom);
  172. case SocketOperation.Send:
  173. return new SocketAsyncCall (worker.Send);
  174. case SocketOperation.SendTo:
  175. return new SocketAsyncCall (worker.SendTo);
  176. default:
  177. return null; // never happens
  178. }
  179. }
  180. public void Complete (bool synch)
  181. {
  182. completed_sync = synch;
  183. Complete ();
  184. }
  185. public void Complete (int total)
  186. {
  187. this.total = total;
  188. Complete ();
  189. }
  190. public void Complete (Exception e, bool synch)
  191. {
  192. completed_sync = synch;
  193. delayedException = e;
  194. Complete ();
  195. }
  196. public void Complete (Exception e)
  197. {
  198. delayedException = e;
  199. Complete ();
  200. }
  201. public void Complete (Socket s)
  202. {
  203. acc_socket = s;
  204. Complete ();
  205. }
  206. public void Complete (Socket s, int total)
  207. {
  208. acc_socket = s;
  209. this.total = total;
  210. Complete ();
  211. }
  212. public object AsyncState {
  213. get {
  214. return state;
  215. }
  216. }
  217. public WaitHandle AsyncWaitHandle {
  218. get {
  219. lock (this) {
  220. if (waithandle == null)
  221. waithandle = new ManualResetEvent (completed);
  222. }
  223. return waithandle;
  224. }
  225. set {
  226. waithandle=value;
  227. }
  228. }
  229. public bool CompletedSynchronously {
  230. get {
  231. return(completed_sync);
  232. }
  233. }
  234. public bool IsCompleted {
  235. get {
  236. return(completed);
  237. }
  238. set {
  239. completed=value;
  240. lock (this) {
  241. if (waithandle != null && value) {
  242. ((ManualResetEvent) waithandle).Set ();
  243. }
  244. }
  245. }
  246. }
  247. public Socket Socket {
  248. get {
  249. return acc_socket;
  250. }
  251. }
  252. public int Total {
  253. get { return total; }
  254. set { total = value; }
  255. }
  256. public SocketError ErrorCode
  257. {
  258. get {
  259. #if NET_2_0
  260. SocketException ex = delayedException as SocketException;
  261. if (ex != null)
  262. return(ex.SocketErrorCode);
  263. if (error != 0)
  264. return((SocketError)error);
  265. #endif
  266. return(SocketError.Success);
  267. }
  268. }
  269. }
  270. private sealed class Worker
  271. {
  272. SocketAsyncResult result;
  273. public Worker (SocketAsyncResult ares)
  274. {
  275. this.result = ares;
  276. }
  277. public void Accept ()
  278. {
  279. Socket acc_socket = null;
  280. try {
  281. acc_socket = result.Sock.Accept ();
  282. } catch (Exception e) {
  283. result.Complete (e);
  284. return;
  285. }
  286. result.Complete (acc_socket);
  287. }
  288. /* only used in 2.0 profile and newer, but
  289. * leave in older profiles to keep interface
  290. * to runtime consistent
  291. */
  292. public void AcceptReceive ()
  293. {
  294. Socket acc_socket = null;
  295. try {
  296. if (result.AcceptSocket == null) {
  297. acc_socket = result.Sock.Accept ();
  298. } else {
  299. acc_socket = result.AcceptSocket;
  300. result.Sock.Accept (acc_socket);
  301. }
  302. } catch (Exception e) {
  303. result.Complete (e);
  304. return;
  305. }
  306. int total = 0;
  307. try {
  308. SocketError error;
  309. total = acc_socket.Receive_nochecks (result.Buffer,
  310. result.Offset,
  311. result.Size,
  312. result.SockFlags,
  313. out error);
  314. } catch (Exception e) {
  315. result.Complete (e);
  316. return;
  317. }
  318. result.Complete (acc_socket, total);
  319. }
  320. public void Connect ()
  321. {
  322. /* If result.EndPoint is non-null,
  323. * this is the standard one-address
  324. * connect attempt. Otherwise
  325. * Addresses must be non-null and
  326. * contain a list of addresses to try
  327. * to connect to; the first one to
  328. * succeed causes the rest of the list
  329. * to be ignored.
  330. */
  331. if (result.EndPoint != null) {
  332. try {
  333. if (!result.Sock.Blocking) {
  334. int success;
  335. result.Sock.Poll (-1, SelectMode.SelectWrite, out success);
  336. if (success == 0) {
  337. result.Sock.connected = true;
  338. } else {
  339. result.Complete (new SocketException (success));
  340. return;
  341. }
  342. } else {
  343. result.Sock.seed_endpoint = result.EndPoint;
  344. result.Sock.Connect (result.EndPoint);
  345. result.Sock.connected = true;
  346. }
  347. } catch (Exception e) {
  348. result.Complete (e);
  349. return;
  350. }
  351. result.Complete ();
  352. } else if (result.Addresses != null) {
  353. foreach(IPAddress address in result.Addresses) {
  354. IPEndPoint iep = new IPEndPoint (address, result.Port);
  355. SocketAddress serial = iep.Serialize ();
  356. int error = 0;
  357. Socket.Connect_internal (result.Sock.socket, serial, out error);
  358. if (error == 0) {
  359. result.Sock.connected = true;
  360. result.Sock.seed_endpoint = iep;
  361. result.Complete ();
  362. return;
  363. } else if (error != (int)SocketError.InProgress &&
  364. error != (int)SocketError.WouldBlock) {
  365. continue;
  366. }
  367. if (!result.Sock.Blocking) {
  368. int success;
  369. result.Sock.Poll (-1, SelectMode.SelectWrite, out success);
  370. if (success == 0) {
  371. result.Sock.connected = true;
  372. result.Sock.seed_endpoint = iep;
  373. result.Complete ();
  374. return;
  375. }
  376. }
  377. }
  378. result.Complete (new SocketException ((int)SocketError.InProgress));
  379. } else {
  380. result.Complete (new SocketException ((int)SocketError.AddressNotAvailable));
  381. }
  382. }
  383. /* Also only used in 2.0 profile and newer */
  384. public void Disconnect ()
  385. {
  386. #if NET_2_0
  387. try {
  388. result.Sock.Disconnect (result.ReuseSocket);
  389. } catch (Exception e) {
  390. result.Complete (e);
  391. return;
  392. }
  393. result.Complete ();
  394. #else
  395. result.Complete (new SocketException ((int)SocketError.Fault));
  396. #endif
  397. }
  398. public void Receive ()
  399. {
  400. // Actual recv() done in the runtime
  401. result.Complete ();
  402. }
  403. public void ReceiveFrom ()
  404. {
  405. int total = 0;
  406. try {
  407. total = result.Sock.ReceiveFrom_nochecks (result.Buffer,
  408. result.Offset,
  409. result.Size,
  410. result.SockFlags,
  411. ref result.EndPoint);
  412. } catch (Exception e) {
  413. result.Complete (e);
  414. return;
  415. }
  416. result.Complete (total);
  417. }
  418. int send_so_far;
  419. void UpdateSendValues (int last_sent)
  420. {
  421. if (result.error == 0) {
  422. send_so_far += last_sent;
  423. result.Offset += last_sent;
  424. result.Size -= last_sent;
  425. }
  426. }
  427. public void Send ()
  428. {
  429. // Actual send() done in the runtime
  430. if (result.error == 0) {
  431. UpdateSendValues (result.Total);
  432. if (result.Sock.disposed) {
  433. result.Complete ();
  434. return;
  435. }
  436. if (result.Size > 0) {
  437. SocketAsyncCall sac = new SocketAsyncCall (this.Send);
  438. sac.BeginInvoke (null, result);
  439. return; // Have to finish writing everything. See bug #74475.
  440. }
  441. result.Total = send_so_far;
  442. }
  443. result.Complete ();
  444. }
  445. public void SendTo ()
  446. {
  447. int total = 0;
  448. try {
  449. total = result.Sock.SendTo_nochecks (result.Buffer,
  450. result.Offset,
  451. result.Size,
  452. result.SockFlags,
  453. result.EndPoint);
  454. UpdateSendValues (total);
  455. if (result.Size > 0) {
  456. SocketAsyncCall sac = new SocketAsyncCall (this.SendTo);
  457. sac.BeginInvoke (null, result);
  458. return; // Have to finish writing everything. See bug #74475.
  459. }
  460. result.Total = send_so_far;
  461. } catch (Exception e) {
  462. result.Complete (e);
  463. return;
  464. }
  465. result.Complete ();
  466. }
  467. }
  468. /* the field "socket" is looked up by name by the runtime */
  469. private IntPtr socket;
  470. private AddressFamily address_family;
  471. private SocketType socket_type;
  472. private ProtocolType protocol_type;
  473. internal bool blocking=true;
  474. private Queue readQ = new Queue (2);
  475. private Queue writeQ = new Queue (2);
  476. delegate void SocketAsyncCall ();
  477. /*
  478. * These two fields are looked up by name by the runtime, don't change
  479. * their name without also updating the runtime code.
  480. */
  481. private static int ipv4Supported = -1, ipv6Supported = -1;
  482. /* When true, the socket was connected at the time of
  483. * the last IO operation
  484. */
  485. private bool connected;
  486. /* true if we called Close_internal */
  487. private bool closed;
  488. internal bool disposed;
  489. /*
  490. * This EndPoint is used when creating new endpoints. Because
  491. * there are many types of EndPoints possible,
  492. * seed_endpoint.Create(addr) is used for creating new ones.
  493. * As such, this value is set on Bind, SentTo, ReceiveFrom,
  494. * Connect, etc.
  495. */
  496. private EndPoint seed_endpoint = null;
  497. #if NET_2_0
  498. private bool isbound;
  499. private bool islistening;
  500. private bool useoverlappedIO;
  501. #endif
  502. static void AddSockets (ArrayList sockets, IList list, string name)
  503. {
  504. if (list != null) {
  505. foreach (Socket sock in list) {
  506. if (sock == null) // MS throws a NullRef
  507. throw new ArgumentNullException ("name", "Contains a null element");
  508. sockets.Add (sock);
  509. }
  510. }
  511. sockets.Add (null);
  512. }
  513. #if !TARGET_JVM
  514. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  515. private extern static void Select_internal (ref Socket [] sockets,
  516. int microSeconds,
  517. out int error);
  518. #endif
  519. public static void Select (IList checkRead, IList checkWrite, IList checkError, int microSeconds)
  520. {
  521. ArrayList list = new ArrayList ();
  522. AddSockets (list, checkRead, "checkRead");
  523. AddSockets (list, checkWrite, "checkWrite");
  524. AddSockets (list, checkError, "checkError");
  525. if (list.Count == 3) {
  526. throw new ArgumentNullException ("checkRead, checkWrite, checkError",
  527. "All the lists are null or empty.");
  528. }
  529. int error;
  530. /*
  531. * The 'sockets' array contains: READ socket 0-n, null,
  532. * WRITE socket 0-n, null,
  533. * ERROR socket 0-n, null
  534. */
  535. Socket [] sockets = (Socket []) list.ToArray (typeof (Socket));
  536. Select_internal (ref sockets, microSeconds, out error);
  537. if (error != 0)
  538. throw new SocketException (error);
  539. if (checkRead != null)
  540. checkRead.Clear ();
  541. if (checkWrite != null)
  542. checkWrite.Clear ();
  543. if (checkError != null)
  544. checkError.Clear ();
  545. if (sockets == null)
  546. return;
  547. int mode = 0;
  548. int count = sockets.Length;
  549. IList currentList = checkRead;
  550. for (int i = 0; i < count; i++) {
  551. Socket sock = sockets [i];
  552. if (sock == null) { // separator
  553. currentList = (mode == 0) ? checkWrite : checkError;
  554. mode++;
  555. continue;
  556. }
  557. if (currentList != null) {
  558. if (currentList == checkWrite && !sock.connected) {
  559. if ((int) sock.GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error) == 0) {
  560. sock.connected = true;
  561. }
  562. }
  563. currentList.Add (sock);
  564. }
  565. }
  566. }
  567. // private constructor used by Accept, which already
  568. // has a socket handle to use
  569. private Socket(AddressFamily family, SocketType type,
  570. ProtocolType proto, IntPtr sock)
  571. {
  572. address_family=family;
  573. socket_type=type;
  574. protocol_type=proto;
  575. socket=sock;
  576. connected=true;
  577. }
  578. #if !TARGET_JVM
  579. // Creates a new system socket, returning the handle
  580. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  581. private extern IntPtr Socket_internal(AddressFamily family,
  582. SocketType type,
  583. ProtocolType proto,
  584. out int error);
  585. #endif
  586. private void SocketDefaults ()
  587. {
  588. #if NET_2_0
  589. try {
  590. if (address_family == AddressFamily.InterNetwork /* Need to test IPv6 further ||
  591. address_family == AddressFamily.InterNetworkV6 */) {
  592. /* This is the default, but it
  593. * probably has nasty side
  594. * effects on Linux, as the
  595. * socket option is kludged by
  596. * turning on or off PMTU
  597. * discovery...
  598. */
  599. this.DontFragment = false;
  600. }
  601. /* Set the same defaults as the MS runtime */
  602. this.ReceiveBufferSize = 8192;
  603. this.SendBufferSize = 8192;
  604. } catch (SocketException) {
  605. }
  606. #endif
  607. }
  608. public Socket(AddressFamily family, SocketType type, ProtocolType proto)
  609. {
  610. address_family=family;
  611. socket_type=type;
  612. protocol_type=proto;
  613. int error;
  614. socket = Socket_internal (family, type, proto, out error);
  615. if (error != 0)
  616. throw new SocketException (error);
  617. SocketDefaults ();
  618. }
  619. #if NET_2_0
  620. [MonoTODO]
  621. public Socket (SocketInformation socketInformation)
  622. {
  623. throw new NotImplementedException ("SocketInformation not figured out yet");
  624. //address_family = socketInformation.address_family;
  625. //socket_type = socketInformation.socket_type;
  626. //protocol_type = socketInformation.protocol_type;
  627. address_family = AddressFamily.InterNetwork;
  628. socket_type = SocketType.Stream;
  629. protocol_type = ProtocolType.IP;
  630. int error;
  631. socket = Socket_internal (address_family, socket_type, protocol_type, out error);
  632. if (error != 0)
  633. throw new SocketException (error);
  634. SocketDefaults ();
  635. }
  636. #endif
  637. public AddressFamily AddressFamily {
  638. get {
  639. return(address_family);
  640. }
  641. }
  642. #if !TARGET_JVM
  643. // Returns the amount of data waiting to be read on socket
  644. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  645. private extern static int Available_internal(IntPtr socket, out int error);
  646. #endif
  647. public int Available {
  648. get {
  649. if (disposed && closed)
  650. throw new ObjectDisposedException (GetType ().ToString ());
  651. int ret, error;
  652. ret = Available_internal(socket, out error);
  653. if (error != 0)
  654. throw new SocketException (error);
  655. return(ret);
  656. }
  657. }
  658. #if !TARGET_JVM
  659. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  660. private extern static void Blocking_internal(IntPtr socket,
  661. bool block,
  662. out int error);
  663. #endif
  664. public bool Blocking {
  665. get {
  666. return(blocking);
  667. }
  668. set {
  669. if (disposed && closed)
  670. throw new ObjectDisposedException (GetType ().ToString ());
  671. int error;
  672. Blocking_internal (socket, value, out error);
  673. if (error != 0)
  674. throw new SocketException (error);
  675. blocking=value;
  676. }
  677. }
  678. public bool Connected {
  679. get {
  680. return(connected);
  681. }
  682. }
  683. #if NET_2_0
  684. public bool DontFragment {
  685. get {
  686. if (disposed && closed) {
  687. throw new ObjectDisposedException (GetType ().ToString ());
  688. }
  689. bool dontfragment;
  690. if (address_family == AddressFamily.InterNetwork) {
  691. dontfragment = (int)(GetSocketOption (SocketOptionLevel.IP, SocketOptionName.DontFragment)) != 0;
  692. } else if (address_family == AddressFamily.InterNetworkV6) {
  693. dontfragment = (int)(GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.DontFragment)) != 0;
  694. } else {
  695. throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
  696. }
  697. return(dontfragment);
  698. }
  699. set {
  700. if (disposed && closed) {
  701. throw new ObjectDisposedException (GetType ().ToString ());
  702. }
  703. if (address_family == AddressFamily.InterNetwork) {
  704. SetSocketOption (SocketOptionLevel.IP, SocketOptionName.DontFragment, value?1:0);
  705. } else if (address_family == AddressFamily.InterNetworkV6) {
  706. SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.DontFragment, value?1:0);
  707. } else {
  708. throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
  709. }
  710. }
  711. }
  712. public bool EnableBroadcast {
  713. get {
  714. if (disposed && closed) {
  715. throw new ObjectDisposedException (GetType ().ToString ());
  716. }
  717. if (protocol_type != ProtocolType.Udp) {
  718. throw new SocketException ((int)SocketError.ProtocolOption);
  719. }
  720. return((int)(GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Broadcast)) != 0);
  721. }
  722. set {
  723. if (disposed && closed) {
  724. throw new ObjectDisposedException (GetType ().ToString ());
  725. }
  726. if (protocol_type != ProtocolType.Udp) {
  727. throw new SocketException ((int)SocketError.ProtocolOption);
  728. }
  729. SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Broadcast, value?1:0);
  730. }
  731. }
  732. public bool ExclusiveAddressUse {
  733. get {
  734. if (disposed && closed) {
  735. throw new ObjectDisposedException (GetType ().ToString ());
  736. }
  737. return((int)(GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse)) != 0);
  738. }
  739. set {
  740. if (disposed && closed) {
  741. throw new ObjectDisposedException (GetType ().ToString ());
  742. }
  743. if (isbound) {
  744. throw new InvalidOperationException ("Bind has already been called for this socket");
  745. }
  746. SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse, value?1:0);
  747. }
  748. }
  749. public bool IsBound {
  750. get {
  751. return(isbound);
  752. }
  753. }
  754. public LingerOption LingerState {
  755. get {
  756. if (disposed && closed) {
  757. throw new ObjectDisposedException (GetType ().ToString ());
  758. }
  759. return((LingerOption)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Linger));
  760. }
  761. set {
  762. if (disposed && closed) {
  763. throw new ObjectDisposedException (GetType ().ToString ());
  764. }
  765. SetSocketOption (SocketOptionLevel.Socket,
  766. SocketOptionName.Linger,
  767. value);
  768. }
  769. }
  770. public bool MulticastLoopback {
  771. get {
  772. if (disposed && closed) {
  773. throw new ObjectDisposedException (GetType ().ToString ());
  774. }
  775. /* Even though this option can be set
  776. * for TCP sockets on Linux, throw
  777. * this exception anyway to be
  778. * compatible (the MSDN docs say
  779. * "Setting this property on a
  780. * Transmission Control Protocol (TCP)
  781. * socket will have no effect." but
  782. * the MS runtime throws the
  783. * exception...)
  784. */
  785. if (protocol_type == ProtocolType.Tcp) {
  786. throw new SocketException ((int)SocketError.ProtocolOption);
  787. }
  788. bool multicastloopback;
  789. if (address_family == AddressFamily.InterNetwork) {
  790. multicastloopback = (int)(GetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastLoopback)) != 0;
  791. } else if (address_family == AddressFamily.InterNetworkV6) {
  792. multicastloopback = (int)(GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback)) != 0;
  793. } else {
  794. throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
  795. }
  796. return(multicastloopback);
  797. }
  798. set {
  799. if (disposed && closed) {
  800. throw new ObjectDisposedException (GetType ().ToString ());
  801. }
  802. /* Even though this option can be set
  803. * for TCP sockets on Linux, throw
  804. * this exception anyway to be
  805. * compatible (the MSDN docs say
  806. * "Setting this property on a
  807. * Transmission Control Protocol (TCP)
  808. * socket will have no effect." but
  809. * the MS runtime throws the
  810. * exception...)
  811. */
  812. if (protocol_type == ProtocolType.Tcp) {
  813. throw new SocketException ((int)SocketError.ProtocolOption);
  814. }
  815. if (address_family == AddressFamily.InterNetwork) {
  816. SetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastLoopback, value?1:0);
  817. } else if (address_family == AddressFamily.InterNetworkV6) {
  818. SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback, value?1:0);
  819. } else {
  820. throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
  821. }
  822. }
  823. }
  824. public static bool OSSupportsIPv6 {
  825. get {
  826. NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces ();
  827. foreach(NetworkInterface adapter in nics) {
  828. if (adapter.Supports (NetworkInterfaceComponent.IPv6) == true) {
  829. return(true);
  830. } else {
  831. continue;
  832. }
  833. }
  834. return(false);
  835. }
  836. }
  837. public int ReceiveBufferSize {
  838. get {
  839. if (disposed && closed) {
  840. throw new ObjectDisposedException (GetType ().ToString ());
  841. }
  842. return((int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer));
  843. }
  844. set {
  845. if (disposed && closed) {
  846. throw new ObjectDisposedException (GetType ().ToString ());
  847. }
  848. if (value < 0) {
  849. throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
  850. }
  851. SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, value);
  852. }
  853. }
  854. public int SendBufferSize {
  855. get {
  856. if (disposed && closed) {
  857. throw new ObjectDisposedException (GetType ().ToString ());
  858. }
  859. return((int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendBuffer));
  860. }
  861. set {
  862. if (disposed && closed) {
  863. throw new ObjectDisposedException (GetType ().ToString ());
  864. }
  865. if (value < 0) {
  866. throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
  867. }
  868. SetSocketOption (SocketOptionLevel.Socket,
  869. SocketOptionName.SendBuffer,
  870. value);
  871. }
  872. }
  873. public short Ttl {
  874. get {
  875. if (disposed && closed) {
  876. throw new ObjectDisposedException (GetType ().ToString ());
  877. }
  878. short ttl_val;
  879. if (address_family == AddressFamily.InterNetwork) {
  880. ttl_val = (short)((int)GetSocketOption (SocketOptionLevel.IP, SocketOptionName.IpTimeToLive));
  881. } else if (address_family == AddressFamily.InterNetworkV6) {
  882. ttl_val = (short)((int)GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.HopLimit));
  883. } else {
  884. throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
  885. }
  886. return(ttl_val);
  887. }
  888. set {
  889. if (disposed && closed) {
  890. throw new ObjectDisposedException (GetType ().ToString ());
  891. }
  892. if (address_family == AddressFamily.InterNetwork) {
  893. SetSocketOption (SocketOptionLevel.IP, SocketOptionName.IpTimeToLive, value);
  894. } else if (address_family == AddressFamily.InterNetworkV6) {
  895. SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.HopLimit, value);
  896. } else {
  897. throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
  898. }
  899. }
  900. }
  901. [MonoTODO ("This doesn't do anything on Mono yet")]
  902. public bool UseOnlyOverlappedIO {
  903. get {
  904. return(useoverlappedIO);
  905. }
  906. set {
  907. useoverlappedIO = value;
  908. }
  909. }
  910. #endif
  911. public IntPtr Handle {
  912. get {
  913. return(socket);
  914. }
  915. }
  916. Exception GetNotImplemented (string msg)
  917. {
  918. return new NotImplementedException (msg);
  919. }
  920. #if !TARGET_JVM
  921. // Returns the local endpoint details in addr and port
  922. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  923. private extern static SocketAddress LocalEndPoint_internal(IntPtr socket, out int error);
  924. #endif
  925. // Wish: support non-IP endpoints.
  926. public EndPoint LocalEndPoint {
  927. get {
  928. if (disposed && closed)
  929. throw new ObjectDisposedException (GetType ().ToString ());
  930. /*
  931. * If the seed EndPoint is null, Connect, Bind,
  932. * etc has not yet been called. MS returns null
  933. * in this case.
  934. */
  935. if (seed_endpoint == null)
  936. return null;
  937. SocketAddress sa;
  938. int error;
  939. sa=LocalEndPoint_internal(socket, out error);
  940. if (error != 0)
  941. throw new SocketException (error);
  942. return seed_endpoint.Create (sa);
  943. }
  944. }
  945. public ProtocolType ProtocolType {
  946. get {
  947. return(protocol_type);
  948. }
  949. }
  950. // Returns the remote endpoint details in addr and port
  951. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  952. private extern static SocketAddress RemoteEndPoint_internal(IntPtr socket, out int error);
  953. public EndPoint RemoteEndPoint {
  954. get {
  955. if (disposed && closed)
  956. throw new ObjectDisposedException (GetType ().ToString ());
  957. /*
  958. * If the seed EndPoint is null, Connect, Bind,
  959. * etc has not yet been called. MS returns null
  960. * in this case.
  961. */
  962. if (seed_endpoint == null)
  963. return null;
  964. SocketAddress sa;
  965. int error;
  966. sa=RemoteEndPoint_internal(socket, out error);
  967. if (error != 0)
  968. throw new SocketException (error);
  969. return seed_endpoint.Create (sa);
  970. }
  971. }
  972. public SocketType SocketType {
  973. get {
  974. return(socket_type);
  975. }
  976. }
  977. public static bool SupportsIPv4 {
  978. get {
  979. CheckProtocolSupport();
  980. return ipv4Supported == 1;
  981. }
  982. }
  983. #if NET_2_0
  984. [ObsoleteAttribute ("Use OSSupportsIPv6 instead")]
  985. #endif
  986. public static bool SupportsIPv6 {
  987. get {
  988. CheckProtocolSupport();
  989. return ipv6Supported == 1;
  990. }
  991. }
  992. #if NET_2_0
  993. public int SendTimeout {
  994. get {
  995. if (disposed && closed)
  996. throw new ObjectDisposedException (GetType ().ToString ());
  997. return (int)GetSocketOption(
  998. SocketOptionLevel.Socket,
  999. SocketOptionName.SendTimeout);
  1000. }
  1001. set {
  1002. if (disposed && closed)
  1003. throw new ObjectDisposedException (GetType ().ToString ());
  1004. if (value < -1)
  1005. throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than -1");
  1006. /* According to the MSDN docs we
  1007. * should adjust values between 1 and
  1008. * 499 to 500, but the MS runtime
  1009. * doesn't do this.
  1010. */
  1011. if (value == -1)
  1012. value = 0;
  1013. SetSocketOption(
  1014. SocketOptionLevel.Socket,
  1015. SocketOptionName.SendTimeout, value);
  1016. }
  1017. }
  1018. public int ReceiveTimeout {
  1019. get {
  1020. if (disposed && closed)
  1021. throw new ObjectDisposedException (GetType ().ToString ());
  1022. return (int)GetSocketOption(
  1023. SocketOptionLevel.Socket,
  1024. SocketOptionName.ReceiveTimeout);
  1025. }
  1026. set {
  1027. if (disposed && closed)
  1028. throw new ObjectDisposedException (GetType ().ToString ());
  1029. if (value < -1)
  1030. throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than -1");
  1031. if (value == -1) {
  1032. value = 0;
  1033. }
  1034. SetSocketOption(
  1035. SocketOptionLevel.Socket,
  1036. SocketOptionName.ReceiveTimeout, value);
  1037. }
  1038. }
  1039. public bool NoDelay {
  1040. get {
  1041. if (disposed && closed)
  1042. throw new ObjectDisposedException (GetType ().ToString ());
  1043. if (protocol_type == ProtocolType.Udp)
  1044. throw new SocketException ((int)SocketError.ProtocolOption);
  1045. return (int)(GetSocketOption (
  1046. SocketOptionLevel.Tcp,
  1047. SocketOptionName.NoDelay)) != 0;
  1048. }
  1049. set {
  1050. if (disposed && closed)
  1051. throw new ObjectDisposedException (GetType ().ToString ());
  1052. if (protocol_type == ProtocolType.Udp)
  1053. throw new SocketException ((int)SocketError.ProtocolOption);
  1054. SetSocketOption (
  1055. SocketOptionLevel.Tcp,
  1056. SocketOptionName.NoDelay, value ? 1 : 0);
  1057. }
  1058. }
  1059. #endif
  1060. internal static void CheckProtocolSupport ()
  1061. {
  1062. if(ipv4Supported == -1) {
  1063. try {
  1064. Socket tmp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  1065. tmp.Close();
  1066. ipv4Supported = 1;
  1067. } catch {
  1068. ipv4Supported = 0;
  1069. }
  1070. }
  1071. if (ipv6Supported == -1) {
  1072. #if NET_2_0 && CONFIGURATION_DEP
  1073. SettingsSection config;
  1074. config = (SettingsSection) System.Configuration.ConfigurationManager.GetSection ("system.net/settings");
  1075. if (config != null)
  1076. ipv6Supported = config.Ipv6.Enabled ? -1 : 0;
  1077. #else
  1078. NetConfig config = (NetConfig)System.Configuration.ConfigurationSettings.GetConfig("system.net/settings");
  1079. if (config != null)
  1080. ipv6Supported = config.ipv6Enabled ? -1 : 0;
  1081. #endif
  1082. if (ipv6Supported != 0) {
  1083. try {
  1084. Socket tmp = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
  1085. tmp.Close();
  1086. ipv6Supported = 1;
  1087. } catch { }
  1088. }
  1089. }
  1090. }
  1091. // Creates a new system socket, returning the handle
  1092. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1093. private extern static IntPtr Accept_internal(IntPtr sock, out int error);
  1094. Thread blocking_thread;
  1095. public Socket Accept() {
  1096. if (disposed && closed)
  1097. throw new ObjectDisposedException (GetType ().ToString ());
  1098. int error = 0;
  1099. IntPtr sock = (IntPtr) (-1);
  1100. blocking_thread = Thread.CurrentThread;
  1101. try {
  1102. sock = Accept_internal(socket, out error);
  1103. } catch (ThreadAbortException) {
  1104. if (disposed) {
  1105. Thread.ResetAbort ();
  1106. error = (int) SocketError.Interrupted;
  1107. }
  1108. } finally {
  1109. blocking_thread = null;
  1110. }
  1111. if (error != 0)
  1112. throw new SocketException (error);
  1113. Socket accepted = new Socket(this.AddressFamily, this.SocketType,
  1114. this.ProtocolType, sock);
  1115. accepted.seed_endpoint = this.seed_endpoint;
  1116. accepted.Blocking = this.Blocking;
  1117. return(accepted);
  1118. }
  1119. private void Accept (Socket acceptSocket)
  1120. {
  1121. if (disposed && closed)
  1122. throw new ObjectDisposedException (GetType ().ToString ());
  1123. int error = 0;
  1124. IntPtr sock = (IntPtr)(-1);
  1125. blocking_thread = Thread.CurrentThread;
  1126. try {
  1127. sock = Accept_internal (socket, out error);
  1128. } catch (ThreadAbortException) {
  1129. if (disposed) {
  1130. Thread.ResetAbort ();
  1131. error = (int)SocketError.Interrupted;
  1132. }
  1133. } finally {
  1134. blocking_thread = null;
  1135. }
  1136. if (error != 0)
  1137. throw new SocketException (error);
  1138. acceptSocket.address_family = this.AddressFamily;
  1139. acceptSocket.socket_type = this.SocketType;
  1140. acceptSocket.protocol_type = this.ProtocolType;
  1141. acceptSocket.socket = sock;
  1142. acceptSocket.connected = true;
  1143. acceptSocket.seed_endpoint = this.seed_endpoint;
  1144. acceptSocket.Blocking = this.Blocking;
  1145. /* FIXME: figure out what if anything else
  1146. * needs to be reset
  1147. */
  1148. }
  1149. public IAsyncResult BeginAccept(AsyncCallback callback,
  1150. object state)
  1151. {
  1152. if (disposed && closed)
  1153. throw new ObjectDisposedException (GetType ().ToString ());
  1154. #if NET_2_0
  1155. /* FIXME: check the 1.1 docs for this too */
  1156. if (!isbound || !islistening)
  1157. throw new InvalidOperationException ();
  1158. #endif
  1159. SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Accept);
  1160. Worker worker = new Worker (req);
  1161. SocketAsyncCall sac = new SocketAsyncCall (worker.Accept);
  1162. sac.BeginInvoke (null, req);
  1163. return(req);
  1164. }
  1165. #if NET_2_0
  1166. public IAsyncResult BeginAccept (int receiveSize,
  1167. AsyncCallback callback,
  1168. object state)
  1169. {
  1170. if (disposed && closed)
  1171. throw new ObjectDisposedException (GetType ().ToString ());
  1172. if (receiveSize < 0)
  1173. throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
  1174. SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.AcceptReceive);
  1175. Worker worker = new Worker (req);
  1176. SocketAsyncCall sac = new SocketAsyncCall (worker.AcceptReceive);
  1177. req.Buffer = new byte[receiveSize];
  1178. req.Offset = 0;
  1179. req.Size = receiveSize;
  1180. req.SockFlags = SocketFlags.None;
  1181. sac.BeginInvoke (null, req);
  1182. return(req);
  1183. }
  1184. public IAsyncResult BeginAccept (Socket acceptSocket,
  1185. int receiveSize,
  1186. AsyncCallback callback,
  1187. object state)
  1188. {
  1189. if (disposed && closed)
  1190. throw new ObjectDisposedException (GetType ().ToString ());
  1191. if (receiveSize < 0)
  1192. throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
  1193. if (acceptSocket != null) {
  1194. if (acceptSocket.disposed && acceptSocket.closed)
  1195. throw new ObjectDisposedException (acceptSocket.GetType ().ToString ());
  1196. if (acceptSocket.IsBound)
  1197. throw new InvalidOperationException ();
  1198. /* For some reason the MS runtime
  1199. * barfs if the new socket is not TCP,
  1200. * even though it's just about to blow
  1201. * away all those parameters
  1202. */
  1203. if (acceptSocket.ProtocolType != ProtocolType.Tcp)
  1204. throw new SocketException ((int)SocketError.InvalidArgument);
  1205. }
  1206. SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.AcceptReceive);
  1207. Worker worker = new Worker (req);
  1208. SocketAsyncCall sac = new SocketAsyncCall (worker.AcceptReceive);
  1209. req.Buffer = new byte[receiveSize];
  1210. req.Offset = 0;
  1211. req.Size = receiveSize;
  1212. req.SockFlags = SocketFlags.None;
  1213. req.AcceptSocket = acceptSocket;
  1214. sac.BeginInvoke (null, req);
  1215. return(req);
  1216. }
  1217. #endif
  1218. public IAsyncResult BeginConnect(EndPoint end_point,
  1219. AsyncCallback callback,
  1220. object state) {
  1221. if (disposed && closed)
  1222. throw new ObjectDisposedException (GetType ().ToString ());
  1223. if (end_point == null)
  1224. throw new ArgumentNullException ("end_point");
  1225. SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Connect);
  1226. req.EndPoint = end_point;
  1227. // Bug #75154: Connect() should not succeed for .Any addresses.
  1228. if (end_point is IPEndPoint) {
  1229. IPEndPoint ep = (IPEndPoint) end_point;
  1230. if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)) {
  1231. req.Complete (new SocketException ((int) SocketError.AddressNotAvailable), true);
  1232. return req;
  1233. }
  1234. }
  1235. int error = 0;
  1236. if (!blocking) {
  1237. SocketAddress serial = end_point.Serialize ();
  1238. Connect_internal (socket, serial, out error);
  1239. if (error == 0) {
  1240. // succeeded synch
  1241. connected = true;
  1242. req.Complete (true);
  1243. } else if (error != (int) SocketError.InProgress && error != (int) SocketError.WouldBlock) {
  1244. // error synch
  1245. connected = false;
  1246. req.Complete (new SocketException (error), true);
  1247. }
  1248. }
  1249. if (blocking || error == (int) SocketError.InProgress || error == (int) SocketError.WouldBlock) {
  1250. // continue asynch
  1251. connected = false;
  1252. Worker worker = new Worker (req);
  1253. SocketAsyncCall sac = new SocketAsyncCall (worker.Connect);
  1254. sac.BeginInvoke (null, req);
  1255. }
  1256. return(req);
  1257. }
  1258. #if NET_2_0
  1259. public IAsyncResult BeginConnect (IPAddress address, int port,
  1260. AsyncCallback callback,
  1261. object state)
  1262. {
  1263. if (disposed && closed)
  1264. throw new ObjectDisposedException (GetType ().ToString ());
  1265. if (address == null)
  1266. throw new ArgumentNullException ("address");
  1267. if (address.ToString ().Length == 0)
  1268. throw new ArgumentException ("The length of the IP address is zero");
  1269. if (islistening)
  1270. throw new InvalidOperationException ();
  1271. IPEndPoint iep = new IPEndPoint (address, port);
  1272. return(BeginConnect (iep, callback, state));
  1273. }
  1274. public IAsyncResult BeginConnect (IPAddress[] addresses,
  1275. int port,
  1276. AsyncCallback callback,
  1277. object state)
  1278. {
  1279. if (disposed && closed)
  1280. throw new ObjectDisposedException (GetType ().ToString ());
  1281. if (addresses == null)
  1282. throw new ArgumentNullException ("addresses");
  1283. if (this.AddressFamily != AddressFamily.InterNetwork &&
  1284. this.AddressFamily != AddressFamily.InterNetworkV6)
  1285. throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
  1286. if (islistening)
  1287. throw new InvalidOperationException ();
  1288. SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Connect);
  1289. req.Addresses = addresses;
  1290. req.Port = port;
  1291. connected = false;
  1292. Worker worker = new Worker (req);
  1293. SocketAsyncCall sac = new SocketAsyncCall (worker.Connect);
  1294. sac.BeginInvoke (null, req);
  1295. return(req);
  1296. }
  1297. public IAsyncResult BeginConnect (string host, int port,
  1298. AsyncCallback callback,
  1299. object state)
  1300. {
  1301. if (disposed && closed)
  1302. throw new ObjectDisposedException (GetType ().ToString ());
  1303. if (host == null)
  1304. throw new ArgumentNullException ("host");
  1305. if (address_family != AddressFamily.InterNetwork &&
  1306. address_family != AddressFamily.InterNetworkV6)
  1307. throw new NotSupportedException ("This method is valid only for sockets in the InterNetwork and InterNetworkV6 families");
  1308. if (islistening)
  1309. throw new InvalidOperationException ();
  1310. IPHostEntry hostent = Dns.GetHostEntry (host);
  1311. return (BeginConnect (hostent.AddressList, port, callback, state));
  1312. }
  1313. public IAsyncResult BeginDisconnect (bool reuseSocket,
  1314. AsyncCallback callback,
  1315. object state)
  1316. {
  1317. if (disposed && closed)
  1318. throw new ObjectDisposedException (GetType ().ToString ());
  1319. SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Disconnect);
  1320. req.ReuseSocket = reuseSocket;
  1321. Worker worker = new Worker (req);
  1322. SocketAsyncCall sac = new SocketAsyncCall (worker.Disconnect);
  1323. sac.BeginInvoke (null, req);
  1324. return(req);
  1325. }
  1326. #endif
  1327. public IAsyncResult BeginReceive(byte[] buffer, int offset,
  1328. int size,
  1329. SocketFlags socket_flags,
  1330. AsyncCallback callback,
  1331. object state) {
  1332. if (disposed && closed)
  1333. throw new ObjectDisposedException (GetType ().ToString ());
  1334. if (buffer == null)
  1335. throw new ArgumentNullException ("buffer");
  1336. if (offset < 0 || offset > buffer.Length)
  1337. throw new ArgumentOutOfRangeException ("offset");
  1338. if (size < 0 || offset + size > buffer.Length)
  1339. throw new ArgumentOutOfRangeException ("size");
  1340. SocketAsyncResult req;
  1341. lock (readQ) {
  1342. req = new SocketAsyncResult (this, state, callback, SocketOperation.Receive);
  1343. req.Buffer = buffer;
  1344. req.Offset = offset;
  1345. req.Size = size;
  1346. req.SockFlags = socket_flags;
  1347. readQ.Enqueue (req);
  1348. if (readQ.Count == 1) {
  1349. Worker worker = new Worker (req);
  1350. SocketAsyncCall sac = new SocketAsyncCall (worker.Receive);
  1351. sac.BeginInvoke (null, req);
  1352. }
  1353. }
  1354. return req;
  1355. }
  1356. #if NET_2_0
  1357. public IAsyncResult BeginReceive (byte[] buffer, int offset,
  1358. int size, SocketFlags flags,
  1359. out SocketError error,
  1360. AsyncCallback callback,
  1361. object state)
  1362. {
  1363. /* As far as I can tell from the docs and from
  1364. * experimentation, a pointer to the
  1365. * SocketError parameter is not supposed to be
  1366. * saved for the async parts. And as we don't
  1367. * set any socket errors in the setup code, we
  1368. * just have to set it to Success.
  1369. */
  1370. error = SocketError.Success;
  1371. return (BeginReceive (buffer, offset, size, flags, callback, state));
  1372. }
  1373. [CLSCompliant (false)]
  1374. public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers,
  1375. SocketFlags socketFlags,
  1376. AsyncCallback callback,
  1377. object state)
  1378. {
  1379. if (disposed && closed)
  1380. throw new ObjectDisposedException (GetType ().ToString ());
  1381. if (buffers == null)
  1382. throw new ArgumentNullException ("buffers");
  1383. SocketAsyncResult req;
  1384. lock(readQ) {
  1385. req = new SocketAsyncResult (this, state, callback, SocketOperation.Receive);
  1386. req.Buffers = buffers;
  1387. req.SockFlags = socketFlags;
  1388. readQ.Enqueue (req);
  1389. if (readQ.Count == 1) {
  1390. Worker worker = new Worker (req);
  1391. SocketAsyncCall sac = new SocketAsyncCall (worker.Receive);
  1392. sac.BeginInvoke (null, req);
  1393. }
  1394. }
  1395. return(req);
  1396. }
  1397. [CLSCompliant (false)]
  1398. public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers,
  1399. SocketFlags socketFlags,
  1400. out SocketError errorCode,
  1401. AsyncCallback callback,
  1402. object state)
  1403. {
  1404. /* I assume the same SocketError semantics as
  1405. * above
  1406. */
  1407. errorCode = SocketError.Success;
  1408. return (BeginReceive (buffers, socketFlags, callback, state));
  1409. }
  1410. #endif
  1411. public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset,
  1412. int size,
  1413. SocketFlags socket_flags,
  1414. ref EndPoint remote_end,
  1415. AsyncCallback callback,
  1416. object state) {
  1417. if (disposed && closed)
  1418. throw new ObjectDisposedException (GetType ().ToString ());
  1419. if (buffer == null)
  1420. throw new ArgumentNullException ("buffer");
  1421. if (offset < 0)
  1422. throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
  1423. if (size < 0)
  1424. throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
  1425. if (offset + size > buffer.Length)
  1426. throw new ArgumentOutOfRangeException ("offset, size", "offset + size exceeds the buffer length");
  1427. SocketAsyncResult req;
  1428. lock (readQ) {
  1429. req = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveFrom);
  1430. req.Buffer = buffer;
  1431. req.Offset = offset;
  1432. req.Size = size;
  1433. req.SockFlags = socket_flags;
  1434. req.EndPoint = remote_end;
  1435. readQ.Enqueue (req);
  1436. if (readQ.Count == 1) {
  1437. Worker worker = new Worker (req);
  1438. SocketAsyncCall sac = new SocketAsyncCall (worker.ReceiveFrom);
  1439. sac.BeginInvoke (null, req);
  1440. }
  1441. }
  1442. return req;
  1443. }
  1444. #if NET_2_0
  1445. [MonoTODO]
  1446. public IAsyncResult BeginReceiveMessageFrom (
  1447. byte[] buffer, int offset, int size,
  1448. SocketFlags socketFlags, ref EndPoint remoteEP,
  1449. AsyncCallback callback, object state)
  1450. {
  1451. if (disposed && closed)
  1452. throw new ObjectDisposedException (GetType ().ToString ());
  1453. if (buffer == null)
  1454. throw new ArgumentNullException ("buffer");
  1455. if (remoteEP == null)
  1456. throw new ArgumentNullException ("remoteEP");
  1457. if (offset < 0 || offset > buffer.Length)
  1458. throw new ArgumentOutOfRangeException ("offset");
  1459. if (size < 0 || offset + size > buffer.Length)
  1460. throw new ArgumentOutOfRangeException ("size");
  1461. throw new NotImplementedException ();
  1462. }
  1463. #endif
  1464. public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socket_flags,
  1465. AsyncCallback callback, object state)
  1466. {
  1467. if (disposed && closed)
  1468. throw new ObjectDisposedException (GetType ().ToString ());
  1469. if (buffer == null)
  1470. throw new ArgumentNullException ("buffer");
  1471. if (offset < 0)
  1472. throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
  1473. if (size < 0)
  1474. throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
  1475. if (offset + size > buffer.Length)
  1476. throw new ArgumentOutOfRangeException ("offset, size", "offset + size exceeds the buffer length");
  1477. #if NET_2_0
  1478. /* TODO: Check this exception in the 1.1 profile */
  1479. if (!connected)
  1480. throw new SocketException ((int)SocketError.NotConnected);
  1481. #endif
  1482. SocketAsyncResult req;
  1483. lock (writeQ) {
  1484. req = new SocketAsyncResult (this, state, callback, SocketOperation.Send);
  1485. req.Buffer = buffer;
  1486. req.Offset = offset;
  1487. req.Size = size;
  1488. req.SockFlags = socket_flags;
  1489. writeQ.Enqueue (req);
  1490. if (writeQ.Count == 1) {
  1491. Worker worker = new Worker (req);
  1492. SocketAsyncCall sac = new SocketAsyncCall (worker.Send);
  1493. sac.BeginInvoke (null, req);
  1494. }
  1495. }
  1496. return req;
  1497. }
  1498. #if NET_2_0
  1499. public IAsyncResult BeginSend (byte[] buffer, int offset,
  1500. int size,
  1501. SocketFlags socketFlags,
  1502. out SocketError errorCode,
  1503. AsyncCallback callback,
  1504. object state)
  1505. {
  1506. if (!connected) {
  1507. errorCode = SocketError.NotConnected;
  1508. throw new SocketException ((int)errorCode);
  1509. }
  1510. errorCode = SocketError.Success;
  1511. return (BeginSend (buffer, offset, size, socketFlags, callback,
  1512. state));
  1513. }
  1514. public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers,
  1515. SocketFlags socketFlags,
  1516. AsyncCallback callback,
  1517. object state)
  1518. {
  1519. if (disposed && closed)
  1520. throw new ObjectDisposedException (GetType ().ToString ());
  1521. if (buffers == null)
  1522. throw new ArgumentNullException ("buffers");
  1523. if (!connected)
  1524. throw new SocketException ((int)SocketError.NotConnected);
  1525. SocketAsyncResult req;
  1526. lock (writeQ) {
  1527. req = new SocketAsyncResult (this, state, callback, SocketOperation.Send);
  1528. req.Buffers = buffers;
  1529. req.SockFlags = socketFlags;
  1530. writeQ.Enqueue (req);
  1531. if (writeQ.Count == 1) {
  1532. Worker worker = new Worker (req);
  1533. SocketAsyncCall sac = new SocketAsyncCall (worker.Send);
  1534. sac.BeginInvoke (null, req);
  1535. }
  1536. }
  1537. return(req);
  1538. }
  1539. [CLSCompliant (false)]
  1540. public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers,
  1541. SocketFlags socketFlags,
  1542. out SocketError errorCode,
  1543. AsyncCallback callback,
  1544. object state)
  1545. {
  1546. if (!connected) {
  1547. errorCode = SocketError.NotConnected;
  1548. throw new SocketException ((int)errorCode);
  1549. }
  1550. errorCode = SocketError.Success;
  1551. return (BeginSend (buffers, socketFlags, callback, state));
  1552. }
  1553. [MonoTODO ("Not implemented")]
  1554. public IAsyncResult BeginSendFile (string fileName,
  1555. AsyncCallback callback,
  1556. object state)
  1557. {
  1558. if (disposed && closed)
  1559. throw new ObjectDisposedException (GetType ().ToString ());
  1560. if (!connected)
  1561. throw new NotSupportedException ();
  1562. if (!File.Exists (fileName))
  1563. throw new FileNotFoundException ();
  1564. throw new NotImplementedException ();
  1565. }
  1566. [MonoTODO ("Not implemented")]
  1567. public IAsyncResult BeginSendFile (string fileName,
  1568. byte[] preBuffer,
  1569. byte[] postBuffer,
  1570. TransmitFileOptions flags,
  1571. AsyncCallback callback,
  1572. object state)
  1573. {
  1574. if (disposed && closed)
  1575. throw new ObjectDisposedException (GetType ().ToString ());
  1576. if (!connected)
  1577. throw new NotSupportedException ();
  1578. if (!File.Exists (fileName))
  1579. throw new FileNotFoundException ();
  1580. throw new NotImplementedException ();
  1581. }
  1582. #endif
  1583. public IAsyncResult BeginSendTo(byte[] buffer, int offset,
  1584. int size,
  1585. SocketFlags socket_flags,
  1586. EndPoint remote_end,
  1587. AsyncCallback callback,
  1588. object state) {
  1589. if (disposed && closed)
  1590. throw new ObjectDisposedException (GetType ().ToString ());
  1591. if (buffer == null)
  1592. throw new ArgumentNullException ("buffer");
  1593. if (offset < 0)
  1594. throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
  1595. if (size < 0)
  1596. throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
  1597. if (offset + size > buffer.Length)
  1598. throw new ArgumentOutOfRangeException ("offset, size", "offset + size exceeds the buffer length");
  1599. SocketAsyncResult req;
  1600. lock (writeQ) {
  1601. req = new SocketAsyncResult (this, state, callback, SocketOperation.SendTo);
  1602. req.Buffer = buffer;
  1603. req.Offset = offset;
  1604. req.Size = size;
  1605. req.SockFlags = socket_flags;
  1606. req.EndPoint = remote_end;
  1607. writeQ.Enqueue (req);
  1608. if (writeQ.Count == 1) {
  1609. Worker worker = new Worker (req);
  1610. SocketAsyncCall sac = new SocketAsyncCall (worker.SendTo);
  1611. sac.BeginInvoke (null, req);
  1612. }
  1613. }
  1614. return req;
  1615. }
  1616. // Creates a new system socket, returning the handle
  1617. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1618. private extern static void Bind_internal(IntPtr sock,
  1619. SocketAddress sa,
  1620. out int error);
  1621. public void Bind(EndPoint local_end) {
  1622. if (disposed && closed)
  1623. throw new ObjectDisposedException (GetType ().ToString ());
  1624. if (local_end == null)
  1625. throw new ArgumentNullException("local_end");
  1626. int error;
  1627. Bind_internal(socket, local_end.Serialize(), out error);
  1628. if (error != 0)
  1629. throw new SocketException (error);
  1630. #if NET_2_0
  1631. if (error == 0)
  1632. isbound = true;
  1633. #endif
  1634. seed_endpoint = local_end;
  1635. }
  1636. // Closes the socket
  1637. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1638. private extern static void Close_internal(IntPtr socket, out int error);
  1639. public void Close()
  1640. {
  1641. ((IDisposable) this).Dispose ();
  1642. }
  1643. #if NET_2_0
  1644. public void Close (int timeout)
  1645. {
  1646. System.Timers.Timer close_timer = new System.Timers.Timer ();
  1647. close_timer.Elapsed += new ElapsedEventHandler (OnTimeoutClose);
  1648. close_timer.Interval = timeout * 1000;
  1649. close_timer.AutoReset = false;
  1650. close_timer.Enabled = true;
  1651. }
  1652. private void OnTimeoutClose (object source, ElapsedEventArgs e)
  1653. {
  1654. this.Close ();
  1655. }
  1656. #endif
  1657. // Connects to the remote address
  1658. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1659. private extern static void Connect_internal(IntPtr sock,
  1660. SocketAddress sa,
  1661. out int error);
  1662. public void Connect(EndPoint remote_end) {
  1663. if (disposed && closed)
  1664. throw new ObjectDisposedException (GetType ().ToString ());
  1665. if (remote_end == null)
  1666. throw new ArgumentNullException("remote_end");
  1667. if (remote_end is IPEndPoint) {
  1668. IPEndPoint ep = (IPEndPoint) remote_end;
  1669. if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any))
  1670. throw new SocketException ((int) SocketError.AddressNotAvailable);
  1671. }
  1672. #if NET_2_0
  1673. /* TODO: check this for the 1.1 profile too */
  1674. if (islistening)
  1675. throw new InvalidOperationException ();
  1676. #endif
  1677. SocketAddress serial = remote_end.Serialize ();
  1678. int error = 0;
  1679. blocking_thread = Thread.CurrentThread;
  1680. try {
  1681. Connect_internal (socket, serial, out error);
  1682. } catch (ThreadAbortException) {
  1683. if (disposed) {
  1684. Thread.ResetAbort ();
  1685. error = (int) SocketError.Interrupted;
  1686. }
  1687. } finally {
  1688. blocking_thread = null;
  1689. }
  1690. if (error != 0)
  1691. throw new SocketException (error);
  1692. connected=true;
  1693. #if NET_2_0
  1694. isbound = true;
  1695. #endif
  1696. seed_endpoint = remote_end;
  1697. }
  1698. #if NET_2_0
  1699. public void Connect (IPAddress address, int port)
  1700. {
  1701. Connect (new IPEndPoint (address, port));
  1702. }
  1703. public void Connect (IPAddress[] addresses, int port)
  1704. {
  1705. if (disposed && closed)
  1706. throw new ObjectDisposedException (GetType ().ToString ());
  1707. if (addresses == null)
  1708. throw new ArgumentNullException ("addresses");
  1709. if (this.AddressFamily != AddressFamily.InterNetwork &&
  1710. this.AddressFamily != AddressFamily.InterNetworkV6)
  1711. throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
  1712. if (islistening)
  1713. throw new InvalidOperationException ();
  1714. /* FIXME: do non-blocking sockets Poll here? */
  1715. foreach (IPAddress address in addresses) {
  1716. IPEndPoint iep = new IPEndPoint (address,
  1717. port);
  1718. SocketAddress serial = iep.Serialize ();
  1719. int error = 0;
  1720. Connect_internal (socket, serial, out error);
  1721. if (error == 0) {
  1722. connected = true;
  1723. seed_endpoint = iep;
  1724. return;
  1725. } else if (error != (int)SocketError.InProgress &&
  1726. error != (int)SocketError.WouldBlock) {
  1727. continue;
  1728. }
  1729. if (!blocking) {
  1730. Poll (-1, SelectMode.SelectWrite);
  1731. int success = (int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
  1732. if (success == 0) {
  1733. connected = true;
  1734. seed_endpoint = iep;
  1735. return;
  1736. }
  1737. }
  1738. }
  1739. }
  1740. public void Connect (string host, int port)
  1741. {
  1742. IPHostEntry hostent = Dns.GetHostEntry (host);
  1743. Connect (hostent.AddressList, port);
  1744. }
  1745. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1746. private extern static void Disconnect_internal(IntPtr sock,
  1747. bool reuse,
  1748. out int error);
  1749. /* According to the docs, the MS runtime will throw
  1750. * PlatformNotSupportedException if the platform is
  1751. * newer than w2k. We should be able to cope...
  1752. */
  1753. public void Disconnect (bool reuseSocket)
  1754. {
  1755. if (disposed && closed)
  1756. throw new ObjectDisposedException (GetType ().ToString ());
  1757. int error = 0;
  1758. Disconnect_internal (socket, reuseSocket, out error);
  1759. if (error != 0) {
  1760. if (error == 50) {
  1761. /* ERROR_NOT_SUPPORTED */
  1762. throw new PlatformNotSupportedException ();
  1763. } else {
  1764. throw new SocketException (error);
  1765. }
  1766. }
  1767. connected = false;
  1768. if (reuseSocket) {
  1769. /* Do managed housekeeping here... */
  1770. }
  1771. }
  1772. [MonoTODO ("Not implemented")]
  1773. public SocketInformation DuplicateAndClose (int targetProcessId)
  1774. {
  1775. /* Need to serialize this socket into a
  1776. * SocketInformation struct, but must study
  1777. * the MS implementation harder to figure out
  1778. * behaviour as documentation is lacking
  1779. */
  1780. throw new NotImplementedException ();
  1781. }
  1782. #endif
  1783. public Socket EndAccept (IAsyncResult result)
  1784. {
  1785. int bytes;
  1786. byte[] buffer;
  1787. return(EndAccept (out buffer, out bytes, result));
  1788. }
  1789. #if NET_2_0
  1790. public Socket EndAccept (out byte[] buffer,
  1791. IAsyncResult asyncResult)
  1792. {
  1793. int bytes;
  1794. return(EndAccept (out buffer, out bytes, asyncResult));
  1795. }
  1796. #endif
  1797. #if NET_2_0
  1798. public
  1799. #else
  1800. private
  1801. #endif
  1802. Socket EndAccept (out byte[] buffer, out int bytesTransferred,
  1803. IAsyncResult asyncResult)
  1804. {
  1805. if (disposed && closed)
  1806. throw new ObjectDisposedException (GetType ().ToString ());
  1807. if (asyncResult == null)
  1808. throw new ArgumentNullException ("asyncResult");
  1809. SocketAsyncResult req = asyncResult as SocketAsyncResult;
  1810. if (req == null)
  1811. throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
  1812. if (!asyncResult.IsCompleted)
  1813. asyncResult.AsyncWaitHandle.WaitOne ();
  1814. req.CheckIfThrowDelayedException ();
  1815. buffer = req.Buffer;
  1816. bytesTransferred = req.Total;
  1817. return(req.Socket);
  1818. }
  1819. public void EndConnect (IAsyncResult result)
  1820. {
  1821. if (disposed && closed)
  1822. throw new ObjectDisposedException (GetType ().ToString ());
  1823. if (result == null)
  1824. throw new ArgumentNullException ("result");
  1825. SocketAsyncResult req = result as SocketAsyncResult;
  1826. if (req == null)
  1827. throw new ArgumentException ("Invalid IAsyncResult", "result");
  1828. if (!result.IsCompleted)
  1829. result.AsyncWaitHandle.WaitOne();
  1830. req.CheckIfThrowDelayedException();
  1831. }
  1832. #if NET_2_0
  1833. public void EndDisconnect (IAsyncResult asyncResult)
  1834. {
  1835. if (disposed && closed)
  1836. throw new ObjectDisposedException (GetType ().ToString ());
  1837. if (asyncResult == null)
  1838. throw new ArgumentNullException ("asyncResult");
  1839. SocketAsyncResult req = asyncResult as SocketAsyncResult;
  1840. if (req == null)
  1841. throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
  1842. if (!asyncResult.IsCompleted)
  1843. asyncResult.AsyncWaitHandle.WaitOne ();
  1844. req.CheckIfThrowDelayedException ();
  1845. }
  1846. #endif
  1847. public int EndReceive (IAsyncResult result)
  1848. {
  1849. SocketError error;
  1850. return (EndReceive (result, out error));
  1851. }
  1852. #if NET_2_0
  1853. public
  1854. #else
  1855. private
  1856. #endif
  1857. int EndReceive (IAsyncResult asyncResult, out SocketError errorCode)
  1858. {
  1859. if (disposed && closed)
  1860. throw new ObjectDisposedException (GetType ().ToString ());
  1861. if (asyncResult == null)
  1862. throw new ArgumentNullException ("asyncResult");
  1863. SocketAsyncResult req = asyncResult as SocketAsyncResult;
  1864. if (req == null)
  1865. throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
  1866. if (!asyncResult.IsCompleted)
  1867. asyncResult.AsyncWaitHandle.WaitOne ();
  1868. errorCode = req.ErrorCode;
  1869. req.CheckIfThrowDelayedException ();
  1870. return(req.Total);
  1871. }
  1872. public int EndReceiveFrom(IAsyncResult result, ref EndPoint end_point)
  1873. {
  1874. if (disposed && closed)
  1875. throw new ObjectDisposedException (GetType ().ToString ());
  1876. if (result == null)
  1877. throw new ArgumentNullException ("result");
  1878. SocketAsyncResult req = result as SocketAsyncResult;
  1879. if (req == null)
  1880. throw new ArgumentException ("Invalid IAsyncResult", "result");
  1881. if (!result.IsCompleted)
  1882. result.AsyncWaitHandle.WaitOne();
  1883. req.CheckIfThrowDelayedException();
  1884. end_point = req.EndPoint;
  1885. return req.Total;
  1886. }
  1887. #if NET_2_0
  1888. [MonoTODO]
  1889. public int EndReceiveMessageFrom (IAsyncResult asyncResult,
  1890. ref SocketFlags socketFlags,
  1891. ref EndPoint endPoint,
  1892. out IPPacketInformation ipPacketInformation)
  1893. {
  1894. if (disposed && closed)
  1895. throw new ObjectDisposedException (GetType ().ToString ());
  1896. if (asyncResult == null)
  1897. throw new ArgumentNullException ("asyncResult");
  1898. if (endPoint == null)
  1899. throw new ArgumentNullException ("endPoint");
  1900. SocketAsyncResult req = asyncResult as SocketAsyncResult;
  1901. if (req == null)
  1902. throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
  1903. throw new NotImplementedException ();
  1904. }
  1905. #endif
  1906. public int EndSend (IAsyncResult result)
  1907. {
  1908. SocketError error;
  1909. return(EndSend (result, out error));
  1910. }
  1911. #if NET_2_0
  1912. public
  1913. #else
  1914. private
  1915. #endif
  1916. int EndSend (IAsyncResult asyncResult, out SocketError errorCode)
  1917. {
  1918. if (disposed && closed)
  1919. throw new ObjectDisposedException (GetType ().ToString ());
  1920. if (asyncResult == null)
  1921. throw new ArgumentNullException ("asyncResult");
  1922. SocketAsyncResult req = asyncResult as SocketAsyncResult;
  1923. if (req == null)
  1924. throw new ArgumentException ("Invalid IAsyncResult", "result");
  1925. if (!asyncResult.IsCompleted)
  1926. asyncResult.AsyncWaitHandle.WaitOne ();
  1927. errorCode = req.ErrorCode;
  1928. req.CheckIfThrowDelayedException ();
  1929. return(req.Total);
  1930. }
  1931. #if NET_2_0
  1932. [MonoTODO]
  1933. public void EndSendFile (IAsyncResult asyncResult)
  1934. {
  1935. if (disposed && closed)
  1936. throw new ObjectDisposedException (GetType ().ToString ());
  1937. if (asyncResult == null)
  1938. throw new ArgumentNullException ("asyncResult");
  1939. SocketAsyncResult req = asyncResult as SocketAsyncResult;
  1940. if (req == null)
  1941. throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
  1942. throw new NotImplementedException ();
  1943. }
  1944. #endif
  1945. public int EndSendTo (IAsyncResult result)
  1946. {
  1947. if (disposed && closed)
  1948. throw new ObjectDisposedException (GetType ().ToString ());
  1949. if (result == null)
  1950. throw new ArgumentNullException ("result");
  1951. SocketAsyncResult req = result as SocketAsyncResult;
  1952. if (req == null)
  1953. throw new ArgumentException ("Invalid IAsyncResult", "result");
  1954. if (!result.IsCompleted)
  1955. result.AsyncWaitHandle.WaitOne();
  1956. req.CheckIfThrowDelayedException();
  1957. return req.Total;
  1958. }
  1959. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1960. private extern static void GetSocketOption_obj_internal(IntPtr socket,
  1961. SocketOptionLevel level, SocketOptionName name, out object obj_val,
  1962. out int error);
  1963. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1964. private extern static void GetSocketOption_arr_internal(IntPtr socket,
  1965. SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val,
  1966. out int error);
  1967. public object GetSocketOption (SocketOptionLevel level, SocketOptionName name)
  1968. {
  1969. if (disposed && closed)
  1970. throw new ObjectDisposedException (GetType ().ToString ());
  1971. object obj_val;
  1972. int error;
  1973. GetSocketOption_obj_internal(socket, level, name, out obj_val,
  1974. out error);
  1975. if (error != 0)
  1976. throw new SocketException (error);
  1977. if (name == SocketOptionName.Linger) {
  1978. return((LingerOption)obj_val);
  1979. } else if (name==SocketOptionName.AddMembership ||
  1980. name==SocketOptionName.DropMembership) {
  1981. return((MulticastOption)obj_val);
  1982. } else if (obj_val is int) {
  1983. return((int)obj_val);
  1984. } else {
  1985. return(obj_val);
  1986. }
  1987. }
  1988. public void GetSocketOption (SocketOptionLevel level, SocketOptionName name, byte [] opt_value)
  1989. {
  1990. if (disposed && closed)
  1991. throw new ObjectDisposedException (GetType ().ToString ());
  1992. int error;
  1993. GetSocketOption_arr_internal(socket, level, name, ref opt_value,
  1994. out error);
  1995. if (error != 0)
  1996. throw new SocketException (error);
  1997. }
  1998. public byte [] GetSocketOption (SocketOptionLevel level, SocketOptionName name, int length)
  1999. {
  2000. if (disposed && closed)
  2001. throw new ObjectDisposedException (GetType ().ToString ());
  2002. byte[] byte_val=new byte[length];
  2003. int error;
  2004. GetSocketOption_arr_internal(socket, level, name, ref byte_val,
  2005. out error);
  2006. if (error != 0)
  2007. throw new SocketException (error);
  2008. return(byte_val);
  2009. }
  2010. // See Socket.IOControl, WSAIoctl documentation in MSDN. The
  2011. // common options between UNIX and Winsock are FIONREAD,
  2012. // FIONBIO and SIOCATMARK. Anything else will depend on the
  2013. // system.
  2014. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  2015. extern static int WSAIoctl (IntPtr sock, int ioctl_code, byte [] input,
  2016. byte [] output, out int error);
  2017. public int IOControl (int ioctl_code, byte [] in_value, byte [] out_value)
  2018. {
  2019. if (disposed)
  2020. throw new ObjectDisposedException (GetType ().ToString ());
  2021. int error;
  2022. int result = WSAIoctl (socket, ioctl_code, in_value, out_value,
  2023. out error);
  2024. if (error != 0)
  2025. throw new SocketException (error);
  2026. if (result == -1)
  2027. throw new InvalidOperationException ("Must use Blocking property instead.");
  2028. return result;
  2029. }
  2030. #if NET_2_0
  2031. [MonoTODO]
  2032. public int IOControl (IOControlCode ioControlCode,
  2033. byte[] optionInValue,
  2034. byte[] optionOutValue)
  2035. {
  2036. /* Probably just needs to mirror the int
  2037. * overload, but more investigation needed.
  2038. */
  2039. throw new NotImplementedException ();
  2040. }
  2041. #endif
  2042. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  2043. private extern static void Listen_internal(IntPtr sock, int backlog,
  2044. out int error);
  2045. public void Listen (int backlog)
  2046. {
  2047. if (disposed && closed)
  2048. throw new ObjectDisposedException (GetType ().ToString ());
  2049. #if NET_2_0
  2050. /* TODO: check if this should be thrown in the
  2051. * 1.1 profile too
  2052. */
  2053. if (!isbound)
  2054. throw new SocketException ((int)SocketError.InvalidArgument);
  2055. #endif
  2056. int error;
  2057. Listen_internal(socket, backlog, out error);
  2058. if (error != 0)
  2059. throw new SocketException (error);
  2060. #if NET_2_0
  2061. islistening = true;
  2062. #endif
  2063. }
  2064. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  2065. extern static bool Poll_internal (IntPtr socket, SelectMode mode, int timeout, out int error);
  2066. public bool Poll (int time_us, SelectMode mode)
  2067. {
  2068. if (disposed && closed)
  2069. throw new ObjectDisposedException (GetType ().ToString ());
  2070. if (mode != SelectMode.SelectRead &&
  2071. mode != SelectMode.SelectWrite &&
  2072. mode != SelectMode.SelectError)
  2073. throw new NotSupportedException ("'mode' parameter is not valid.");
  2074. int error;
  2075. bool result = Poll_internal (socket, mode, time_us, out error);
  2076. if (error != 0)
  2077. throw new SocketException (error);
  2078. if (mode == SelectMode.SelectWrite && result && !connected) {
  2079. /* Update the connected state; for
  2080. * non-blocking Connect()s this is
  2081. * when we can find out that the
  2082. * connect succeeded.
  2083. */
  2084. if ((int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error) == 0) {
  2085. connected = true;
  2086. }
  2087. }
  2088. return result;
  2089. }
  2090. /* This overload is needed as the async Connect method
  2091. * also needs to check the socket error status, but
  2092. * getsockopt(..., SO_ERROR) clears the error.
  2093. */
  2094. private bool Poll (int time_us, SelectMode mode, out int socket_error)
  2095. {
  2096. if (disposed && closed)
  2097. throw new ObjectDisposedException (GetType ().ToString ());
  2098. if (mode != SelectMode.SelectRead &&
  2099. mode != SelectMode.SelectWrite &&
  2100. mode != SelectMode.SelectError)
  2101. throw new NotSupportedException ("'mode' parameter is not valid.");
  2102. int error;
  2103. bool result = Poll_internal (socket, mode, time_us, out error);
  2104. if (error != 0)
  2105. throw new SocketException (error);
  2106. socket_error = (int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
  2107. if (mode == SelectMode.SelectWrite && result) {
  2108. /* Update the connected state; for
  2109. * non-blocking Connect()s this is
  2110. * when we can find out that the
  2111. * connect succeeded.
  2112. */
  2113. if (socket_error == 0) {
  2114. connected = true;
  2115. }
  2116. }
  2117. return result;
  2118. }
  2119. public int Receive (byte [] buf)
  2120. {
  2121. if (disposed && closed)
  2122. throw new ObjectDisposedException (GetType ().ToString ());
  2123. if (buf == null)
  2124. throw new ArgumentNullException ("buf");
  2125. SocketError error;
  2126. int ret = Receive_nochecks (buf, 0, buf.Length, SocketFlags.None, out error);
  2127. if (error != SocketError.Success)
  2128. throw new SocketException ((int) error);
  2129. return ret;
  2130. }
  2131. public int Receive (byte [] buf, SocketFlags flags)
  2132. {
  2133. if (disposed && closed)
  2134. throw new ObjectDisposedException (GetType ().ToString ());
  2135. if (buf == null)
  2136. throw new ArgumentNullException ("buf");
  2137. SocketError error;
  2138. int ret = Receive_nochecks (buf, 0, buf.Length, flags, out error);
  2139. if (error != SocketError.Success) {
  2140. if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
  2141. throw new SocketException ((int) error, "Operation timed out.");
  2142. throw new SocketException ((int) error);
  2143. }
  2144. return ret;
  2145. }
  2146. public int Receive (byte [] buf, int size, SocketFlags flags)
  2147. {
  2148. if (disposed && closed)
  2149. throw new ObjectDisposedException (GetType ().ToString ());
  2150. if (buf == null)
  2151. throw new ArgumentNullException ("buf");
  2152. if (size < 0 || size > buf.Length)
  2153. throw new ArgumentOutOfRangeException ("size");
  2154. SocketError error;
  2155. int ret = Receive_nochecks (buf, 0, size, flags, out error);
  2156. if (error != SocketError.Success) {
  2157. if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
  2158. throw new SocketException ((int) error, "Operation timed out.");
  2159. throw new SocketException ((int) error);
  2160. }
  2161. return ret;
  2162. }
  2163. public int Receive (byte [] buf, int offset, int size, SocketFlags flags)
  2164. {
  2165. if (disposed && closed)
  2166. throw new ObjectDisposedException (GetType ().ToString ());
  2167. if (buf == null)
  2168. throw new ArgumentNullException ("buf");
  2169. if (offset < 0 || offset > buf.Length)
  2170. throw new ArgumentOutOfRangeException ("offset");
  2171. if (size < 0 || offset + size > buf.Length)
  2172. throw new ArgumentOutOfRangeException ("size");
  2173. SocketError error;
  2174. int ret = Receive_nochecks (buf, offset, size, flags, out error);
  2175. if (error != SocketError.Success) {
  2176. if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
  2177. throw new SocketException ((int) error, "Operation timed out.");
  2178. throw new SocketException ((int) error);
  2179. }
  2180. return ret;
  2181. }
  2182. #if NET_2_0
  2183. public int Receive (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
  2184. {
  2185. if (disposed && closed)
  2186. throw new ObjectDisposedException (GetType ().ToString ());
  2187. if (buf == null)
  2188. throw new ArgumentNullException ("buf");
  2189. if (offset < 0 || offset > buf.Length)
  2190. throw new ArgumentOutOfRangeException ("offset");
  2191. if (size < 0 || offset + size > buf.Length)
  2192. throw new ArgumentOutOfRangeException ("size");
  2193. return Receive_nochecks (buf, offset, size, flags, out error);
  2194. }
  2195. [MonoTODO]
  2196. public int Receive (IList<ArraySegment<byte>> buffers)
  2197. {
  2198. /* For these generic IList overloads I need to
  2199. * implement WSARecv in the runtime
  2200. */
  2201. throw new NotImplementedException ();
  2202. }
  2203. [CLSCompliant (false)]
  2204. [MonoTODO]
  2205. public int Receive (IList<ArraySegment<byte>> buffers,
  2206. SocketFlags socketFlags)
  2207. {
  2208. throw new NotImplementedException ();
  2209. }
  2210. [CLSCompliant (false)]
  2211. [MonoTODO]
  2212. public int Receive (IList<ArraySegment<byte>> buffers,
  2213. SocketFlags socketFlags,
  2214. out SocketError errorCode)
  2215. {
  2216. throw new NotImplementedException ();
  2217. }
  2218. #endif
  2219. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  2220. private extern static int Receive_internal(IntPtr sock,
  2221. byte[] buffer,
  2222. int offset,
  2223. int count,
  2224. SocketFlags flags,
  2225. out int error);
  2226. int Receive_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
  2227. {
  2228. int nativeError;
  2229. int ret = Receive_internal (socket, buf, offset, size, flags, out nativeError);
  2230. error = (SocketError) nativeError;
  2231. if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress)
  2232. connected = false;
  2233. else
  2234. connected = true;
  2235. return ret;
  2236. }
  2237. public int ReceiveFrom (byte [] buf, ref EndPoint remote_end)
  2238. {
  2239. if (disposed && closed)
  2240. throw new ObjectDisposedException (GetType ().ToString ());
  2241. if (buf == null)
  2242. throw new ArgumentNullException ("buf");
  2243. if (remote_end == null)
  2244. throw new ArgumentNullException ("remote_end");
  2245. return ReceiveFrom_nochecks (buf, 0, buf.Length, SocketFlags.None, ref remote_end);
  2246. }
  2247. public int ReceiveFrom (byte [] buf, SocketFlags flags, ref EndPoint remote_end)
  2248. {
  2249. if (disposed && closed)
  2250. throw new ObjectDisposedException (GetType ().ToString ());
  2251. if (buf == null)
  2252. throw new ArgumentNullException ("buf");
  2253. if (remote_end == null)
  2254. throw new ArgumentNullException ("remote_end");
  2255. return ReceiveFrom_nochecks (buf, 0, buf.Length, flags, ref remote_end);
  2256. }
  2257. public int ReceiveFrom (byte [] buf, int size, SocketFlags flags,
  2258. ref EndPoint remote_end)
  2259. {
  2260. if (disposed && closed)
  2261. throw new ObjectDisposedException (GetType ().ToString ());
  2262. if (buf == null)
  2263. throw new ArgumentNullException ("buf");
  2264. if (remote_end == null)
  2265. throw new ArgumentNullException ("remote_end");
  2266. if (size < 0 || size > buf.Length)
  2267. throw new ArgumentOutOfRangeException ("size");
  2268. return ReceiveFrom_nochecks (buf, 0, size, flags, ref remote_end);
  2269. }
  2270. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  2271. private extern static int RecvFrom_internal(IntPtr sock,
  2272. byte[] buffer,
  2273. int offset,
  2274. int count,
  2275. SocketFlags flags,
  2276. ref SocketAddress sockaddr,
  2277. out int error);
  2278. public int ReceiveFrom (byte [] buf, int offset, int size, SocketFlags flags,
  2279. ref EndPoint remote_end)
  2280. {
  2281. if (disposed && closed)
  2282. throw new ObjectDisposedException (GetType ().ToString ());
  2283. if (buf == null)
  2284. throw new ArgumentNullException ("buf");
  2285. if (remote_end == null)
  2286. throw new ArgumentNullException ("remote_end");
  2287. if (offset < 0 || offset > buf.Length)
  2288. throw new ArgumentOutOfRangeException ("offset");
  2289. if (size < 0 || offset + size > buf.Length)
  2290. throw new ArgumentOutOfRangeException ("size");
  2291. return ReceiveFrom_nochecks (buf, offset, size, flags, ref remote_end);
  2292. }
  2293. int ReceiveFrom_nochecks (byte [] buf, int offset, int size, SocketFlags flags,
  2294. ref EndPoint remote_end)
  2295. {
  2296. SocketAddress sockaddr = remote_end.Serialize();
  2297. int cnt, error;
  2298. cnt = RecvFrom_internal (socket, buf, offset, size, flags, ref sockaddr, out error);
  2299. SocketError err = (SocketError) error;
  2300. if (err != 0) {
  2301. if (err != SocketError.WouldBlock && err != SocketError.InProgress)
  2302. connected = false;
  2303. else if (err == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
  2304. throw new SocketException (error, "Operation timed out.");
  2305. throw new SocketException (error);
  2306. }
  2307. connected = true;
  2308. #if NET_2_0
  2309. isbound = true;
  2310. #endif
  2311. // If sockaddr is null then we're a connection
  2312. // oriented protocol and should ignore the
  2313. // remote_end parameter (see MSDN
  2314. // documentation for Socket.ReceiveFrom(...) )
  2315. if ( sockaddr != null ) {
  2316. // Stupidly, EndPoint.Create() is an
  2317. // instance method
  2318. remote_end = remote_end.Create (sockaddr);
  2319. }
  2320. seed_endpoint = remote_end;
  2321. return cnt;
  2322. }
  2323. #if NET_2_0
  2324. [MonoTODO ("Not implemented")]
  2325. public int ReceiveMessageFrom (byte[] buffer, int offset,
  2326. int size,
  2327. ref SocketFlags socketFlags,
  2328. ref EndPoint remoteEP,
  2329. out IPPacketInformation ipPacketInformation)
  2330. {
  2331. if (disposed && closed)
  2332. throw new ObjectDisposedException (GetType ().ToString ());
  2333. if (buffer == null)
  2334. throw new ArgumentNullException ("buffer");
  2335. if (remoteEP == null)
  2336. throw new ArgumentNullException ("remoteEP");
  2337. if (offset < 0 || offset > buffer.Length)
  2338. throw new ArgumentOutOfRangeException ("offset");
  2339. if (size < 0 || offset + size > buffer.Length)
  2340. throw new ArgumentOutOfRangeException ("size");
  2341. /* FIXME: figure out how we get hold of the
  2342. * IPPacketInformation
  2343. */
  2344. throw new NotImplementedException ();
  2345. }
  2346. #endif
  2347. public int Send (byte [] buf)
  2348. {
  2349. if (disposed && closed)
  2350. throw new ObjectDisposedException (GetType ().ToString ());
  2351. if (buf == null)
  2352. throw new ArgumentNullException ("buf");
  2353. SocketError error;
  2354. int ret = Send_nochecks (buf, 0, buf.Length, SocketFlags.None, out error);
  2355. if (error != SocketError.Success)
  2356. throw new SocketException ((int) error);
  2357. return ret;
  2358. }
  2359. public int Send (byte [] buf, SocketFlags flags)
  2360. {
  2361. if (disposed && closed)
  2362. throw new ObjectDisposedException (GetType ().ToString ());
  2363. if (buf == null)
  2364. throw new ArgumentNullException ("buf");
  2365. SocketError error;
  2366. int ret = Send_nochecks (buf, 0, buf.Length, flags, out error);
  2367. if (error != SocketError.Success)
  2368. throw new SocketException ((int) error);
  2369. return ret;
  2370. }
  2371. public int Send (byte [] buf, int size, SocketFlags flags)
  2372. {
  2373. if (disposed && closed)
  2374. throw new ObjectDisposedException (GetType ().ToString ());
  2375. if (buf == null)
  2376. throw new ArgumentNullException ("buf");
  2377. if (size < 0 || size > buf.Length)
  2378. throw new ArgumentOutOfRangeException ("size");
  2379. SocketError error;
  2380. int ret = Send_nochecks (buf, 0, size, flags, out error);
  2381. if (error != SocketError.Success)
  2382. throw new SocketException ((int) error);
  2383. return ret;
  2384. }
  2385. public int Send (byte [] buf, int offset, int size, SocketFlags flags)
  2386. {
  2387. if (disposed && closed)
  2388. throw new ObjectDisposedException (GetType ().ToString ());
  2389. if (buf == null)
  2390. throw new ArgumentNullException ("buffer");
  2391. if (offset < 0 || offset > buf.Length)
  2392. throw new ArgumentOutOfRangeException ("offset");
  2393. if (size < 0 || offset + size > buf.Length)
  2394. throw new ArgumentOutOfRangeException ("size");
  2395. SocketError error;
  2396. int ret = Send_nochecks (buf, offset, size, flags, out error);
  2397. if (error != SocketError.Success)
  2398. throw new SocketException ((int) error);
  2399. return ret;
  2400. }
  2401. #if NET_2_0
  2402. public int Send (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
  2403. {
  2404. if (disposed && closed)
  2405. throw new ObjectDisposedException (GetType ().ToString ());
  2406. if (buf == null)
  2407. throw new ArgumentNullException ("buffer");
  2408. if (offset < 0 || offset > buf.Length)
  2409. throw new ArgumentOutOfRangeException ("offset");
  2410. if (size < 0 || offset + size > buf.Length)
  2411. throw new ArgumentOutOfRangeException ("size");
  2412. return Send_nochecks (buf, offset, size, flags, out error);
  2413. }
  2414. [MonoTODO]
  2415. public int Send (IList<ArraySegment<byte>> buffers)
  2416. {
  2417. /* For these generic IList overloads I need to
  2418. * implement WSASend in the runtime
  2419. */
  2420. throw new NotImplementedException ();
  2421. }
  2422. [MonoTODO]
  2423. public int Send (IList<ArraySegment<byte>> buffers,
  2424. SocketFlags socketFlags)
  2425. {
  2426. throw new NotImplementedException ();
  2427. }
  2428. [CLSCompliant (false)]
  2429. [MonoTODO]
  2430. public int Send (IList<ArraySegment<byte>> buffers,
  2431. SocketFlags socketFlags,
  2432. out SocketError errorCode)
  2433. {
  2434. throw new NotImplementedException ();
  2435. }
  2436. #endif
  2437. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  2438. private extern static int Send_internal(IntPtr sock,
  2439. byte[] buf, int offset,
  2440. int count,
  2441. SocketFlags flags,
  2442. out int error);
  2443. int Send_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
  2444. {
  2445. if (size == 0) {
  2446. error = SocketError.Success;
  2447. return 0;
  2448. }
  2449. int nativeError;
  2450. int ret = Send_internal (socket, buf, offset, size, flags, out nativeError);
  2451. error = (SocketError)nativeError;
  2452. if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress)
  2453. connected = false;
  2454. else
  2455. connected = true;
  2456. return ret;
  2457. }
  2458. #if NET_2_0
  2459. [MonoTODO ("Not implemented")]
  2460. public void SendFile (string fileName)
  2461. {
  2462. if (disposed && closed)
  2463. throw new ObjectDisposedException (GetType ().ToString ());
  2464. if (!connected)
  2465. throw new NotSupportedException ();
  2466. if (!blocking)
  2467. throw new InvalidOperationException ();
  2468. if (!File.Exists (fileName))
  2469. throw new FileNotFoundException ();
  2470. /* FIXME: Implement TransmitFile */
  2471. throw new NotImplementedException ();
  2472. }
  2473. [MonoTODO ("Not implemented")]
  2474. public void SendFile (string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags)
  2475. {
  2476. if (disposed && closed)
  2477. throw new ObjectDisposedException (GetType ().ToString ());
  2478. if (!connected)
  2479. throw new NotSupportedException ();
  2480. if (!blocking)
  2481. throw new InvalidOperationException ();
  2482. if (!File.Exists (fileName))
  2483. throw new FileNotFoundException ();
  2484. /* FIXME: Implement TransmitFile */
  2485. throw new NotImplementedException ();
  2486. }
  2487. #endif
  2488. public int SendTo (byte [] buffer, EndPoint remote_end)
  2489. {
  2490. if (disposed && closed)
  2491. throw new ObjectDisposedException (GetType ().ToString ());
  2492. if (buffer == null)
  2493. throw new ArgumentNullException ("buffer");
  2494. if (remote_end == null)
  2495. throw new ArgumentNullException ("remote_end");
  2496. return SendTo_nochecks (buffer, 0, buffer.Length, SocketFlags.None, remote_end);
  2497. }
  2498. public int SendTo (byte [] buffer, SocketFlags flags, EndPoint remote_end)
  2499. {
  2500. if (disposed && closed)
  2501. throw new ObjectDisposedException (GetType ().ToString ());
  2502. if (buffer == null)
  2503. throw new ArgumentNullException ("buffer");
  2504. if (remote_end == null)
  2505. throw new ArgumentNullException ("remote_end");
  2506. return SendTo_nochecks (buffer, 0, buffer.Length, flags, remote_end);
  2507. }
  2508. public int SendTo (byte [] buffer, int size, SocketFlags flags, EndPoint remote_end)
  2509. {
  2510. if (disposed && closed)
  2511. throw new ObjectDisposedException (GetType ().ToString ());
  2512. if (buffer == null)
  2513. throw new ArgumentNullException ("buffer");
  2514. if (remote_end == null)
  2515. throw new ArgumentNullException ("remote_end");
  2516. if (size < 0 || size > buffer.Length)
  2517. throw new ArgumentOutOfRangeException ("size");
  2518. return SendTo_nochecks (buffer, 0, size, flags, remote_end);
  2519. }
  2520. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  2521. private extern static int SendTo_internal(IntPtr sock,
  2522. byte[] buffer,
  2523. int offset,
  2524. int count,
  2525. SocketFlags flags,
  2526. SocketAddress sa,
  2527. out int error);
  2528. public int SendTo (byte [] buffer, int offset, int size, SocketFlags flags,
  2529. EndPoint remote_end)
  2530. {
  2531. if (disposed && closed)
  2532. throw new ObjectDisposedException (GetType ().ToString ());
  2533. if (buffer == null)
  2534. throw new ArgumentNullException ("buffer");
  2535. if (remote_end == null)
  2536. throw new ArgumentNullException("remote_end");
  2537. if (offset < 0 || offset > buffer.Length)
  2538. throw new ArgumentOutOfRangeException ("offset");
  2539. if (size < 0 || offset + size > buffer.Length)
  2540. throw new ArgumentOutOfRangeException ("size");
  2541. return SendTo_nochecks (buffer, offset, size, flags, remote_end);
  2542. }
  2543. int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags,
  2544. EndPoint remote_end)
  2545. {
  2546. SocketAddress sockaddr = remote_end.Serialize ();
  2547. int ret, error;
  2548. ret = SendTo_internal (socket, buffer, offset, size, flags, sockaddr, out error);
  2549. SocketError err = (SocketError) error;
  2550. if (err != 0) {
  2551. if (err != SocketError.WouldBlock && err != SocketError.InProgress)
  2552. connected = false;
  2553. throw new SocketException (error);
  2554. }
  2555. connected = true;
  2556. #if NET_2_0
  2557. isbound = true;
  2558. #endif
  2559. seed_endpoint = remote_end;
  2560. return ret;
  2561. }
  2562. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  2563. private extern static void SetSocketOption_internal (IntPtr socket, SocketOptionLevel level,
  2564. SocketOptionName name, object obj_val,
  2565. byte [] byte_val, int int_val,
  2566. out int error);
  2567. public void SetSocketOption (SocketOptionLevel level, SocketOptionName name, byte[] opt_value)
  2568. {
  2569. if (disposed && closed)
  2570. throw new ObjectDisposedException (GetType ().ToString ());
  2571. int error;
  2572. SetSocketOption_internal(socket, level, name, null,
  2573. opt_value, 0, out error);
  2574. if (error != 0)
  2575. throw new SocketException (error);
  2576. }
  2577. public void SetSocketOption (SocketOptionLevel level, SocketOptionName name, int opt_value)
  2578. {
  2579. if (disposed && closed)
  2580. throw new ObjectDisposedException (GetType ().ToString ());
  2581. int error;
  2582. SetSocketOption_internal(socket, level, name, null,
  2583. null, opt_value, out error);
  2584. if (error != 0)
  2585. throw new SocketException (error);
  2586. }
  2587. public void SetSocketOption (SocketOptionLevel level, SocketOptionName name, object opt_value)
  2588. {
  2589. if (disposed && closed)
  2590. throw new ObjectDisposedException (GetType ().ToString ());
  2591. if (opt_value == null)
  2592. throw new ArgumentNullException("opt_value");
  2593. int error;
  2594. /* From MS documentation on SetSocketOption: "For an
  2595. * option with a Boolean data type, specify a nonzero
  2596. * value to enable the option, and a zero value to
  2597. * disable the option."
  2598. * Booleans are only handled in 2.0
  2599. */
  2600. if (opt_value is System.Boolean) {
  2601. #if NET_2_0
  2602. bool bool_val = (bool) opt_value;
  2603. int int_val = (bool_val) ? 1 : 0;
  2604. SetSocketOption_internal (socket, level, name, null, null, int_val, out error);
  2605. #else
  2606. throw new ArgumentException ("Use an integer 1 (true) or 0 (false) instead of a boolean.", "opt_value");
  2607. #endif
  2608. } else {
  2609. SetSocketOption_internal (socket, level, name, opt_value, null, 0, out error);
  2610. }
  2611. if (error != 0)
  2612. throw new SocketException (error);
  2613. }
  2614. #if NET_2_0
  2615. public void SetSocketOption (SocketOptionLevel level, SocketOptionName name, bool optionValue)
  2616. {
  2617. if (disposed && closed)
  2618. throw new ObjectDisposedException (GetType ().ToString ());
  2619. int error;
  2620. int int_val = (optionValue) ? 1 : 0;
  2621. SetSocketOption_internal (socket, level, name, null, null, int_val, out error);
  2622. if (error != 0)
  2623. throw new SocketException (error);
  2624. }
  2625. #endif
  2626. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  2627. private extern static void Shutdown_internal(IntPtr socket, SocketShutdown how, out int error);
  2628. public void Shutdown (SocketShutdown how)
  2629. {
  2630. if (disposed && closed)
  2631. throw new ObjectDisposedException (GetType ().ToString ());
  2632. int error;
  2633. Shutdown_internal (socket, how, out error);
  2634. if (error != 0)
  2635. throw new SocketException (error);
  2636. }
  2637. public override int GetHashCode ()
  2638. {
  2639. return (int) socket;
  2640. }
  2641. protected virtual void Dispose (bool explicitDisposing)
  2642. {
  2643. if (disposed)
  2644. return;
  2645. disposed = true;
  2646. connected = false;
  2647. if ((int) socket != -1) {
  2648. int error;
  2649. closed = true;
  2650. IntPtr x = socket;
  2651. socket = (IntPtr) (-1);
  2652. Close_internal (x, out error);
  2653. if (blocking_thread != null) {
  2654. blocking_thread.Abort ();
  2655. blocking_thread = null;
  2656. }
  2657. if (error != 0)
  2658. throw new SocketException (error);
  2659. }
  2660. }
  2661. void IDisposable.Dispose ()
  2662. {
  2663. Dispose (true);
  2664. GC.SuppressFinalize (this);
  2665. }
  2666. ~Socket () {
  2667. Dispose (false);
  2668. }
  2669. }
  2670. }