PageRenderTime 43ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/base/Applications/TftpClient/tftp.cs

#
C# | 391 lines | 329 code | 33 blank | 29 comment | 61 complexity | e6e584b36544eaa0a70d286f0c7c8c45 MD5 | raw file
  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Microsoft Research Singularity
  4. //
  5. // Copyright (c) Microsoft Corporation. All rights reserved.
  6. //
  7. // Note:
  8. //
  9. using System;
  10. using System.Net.Sockets;
  11. using System.Net;
  12. using System.Text;
  13. using System.Threading;
  14. using Microsoft.Singularity;
  15. using Microsoft.Singularity.Directory;
  16. using Microsoft.Singularity.Channels;
  17. using Microsoft.Singularity.FileSystem;
  18. using Microsoft.Singularity.V1.Services;
  19. using FileSystem.Utils;
  20. namespace Microsoft.Singularity.Applications
  21. {
  22. internal enum TftpOpcode : ushort
  23. {
  24. RRQ=1, WRQ=2, DATA=3, ACK=4, ERROR=5
  25. };
  26. internal struct TftpHdr
  27. {
  28. public TftpOpcode Opcode;
  29. public ushort Arg;
  30. public TftpHdr(byte[]! buffer, int offset)
  31. {
  32. Opcode = (TftpOpcode)((ushort)buffer[offset+0] << 8 | buffer[offset+1]);
  33. Arg = (ushort)((ushort)buffer[offset+2] << 8 | buffer[offset+3]);
  34. // UnMarshal(buffer, offset);
  35. }
  36. public void Marshal(byte[]! buffer, int offset)
  37. {
  38. buffer[offset+0] = (byte)((ushort)Opcode>>8 & 0xff);
  39. buffer[offset+1] = (byte)((ushort)Opcode>>0 & 0xff);
  40. buffer[offset+2] = (byte)(Arg>>8 & 0xff);
  41. buffer[offset+3] = (byte)(Arg>>0 & 0xff);
  42. }
  43. public void UnMarshal(byte[]! buffer, int offset)
  44. {
  45. Opcode = (TftpOpcode)((ushort)buffer[offset+0] << 8 | buffer[offset+1]);
  46. Arg = (ushort)((ushort)buffer[offset+2] << 8 | buffer[offset+3]);
  47. }
  48. };
  49. public class TftpClient
  50. {
  51. Socket! s;
  52. public TftpClient(IPAddress! server)
  53. {
  54. Socket s = this.s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
  55. IPEndPoint ep = new System.Net.IPEndPoint(server, 69);
  56. Console.Write("EP= {0}\n", ep);
  57. // Connect here
  58. s.Connect(ep);
  59. }
  60. static int BuildRequest(byte[]! packet, TftpOpcode op, string! filename)
  61. {
  62. TftpHdr hdr = new TftpHdr();
  63. byte[] tmp;
  64. hdr.Opcode = op;
  65. hdr.Marshal(packet, 0);
  66. int off = 2;
  67. tmp = Encoding.ASCII.GetBytes(filename);
  68. tmp.CopyTo(packet, off);
  69. off += tmp.Length;
  70. packet[off++] = 0;
  71. tmp = Encoding.ASCII.GetBytes("octet");
  72. tmp.CopyTo(packet, off);
  73. off += tmp.Length;
  74. packet[off++] = 0;
  75. Console.WriteLine("Done");
  76. return off;
  77. }
  78. public string Get(string! filename, string localName, bool verboseMode)
  79. {
  80. TftpHdr hdr = new TftpHdr();
  81. byte[] request;
  82. byte[] reply = new byte[8192];
  83. int success;
  84. FileContract.Imp persistHandle = null ;
  85. long curPos = 0 ;
  86. int len;
  87. int rc;
  88. if (null != localName) {
  89. Console.WriteLine ("Creating file "+localName);
  90. success = FileUtils.CreateFile(localName);
  91. if (0 == success) {
  92. persistHandle = FileUtils.OpenFile(localName);
  93. if (null == persistHandle) {
  94. Console.WriteLine("unable to open file " + localName);
  95. return "";
  96. }
  97. }
  98. else {
  99. Console.WriteLine("unable to create file " + localName);
  100. return "";
  101. }
  102. }
  103. request = new byte[4 + 512];
  104. len = BuildRequest(request, TftpOpcode.RRQ, filename);
  105. bool done = false;
  106. hdr.UnMarshal(request, 0);
  107. rc = s.Send(request, len, SocketFlags.None);
  108. if (verboseMode) Console.WriteLine("Sent RRQ rc={0}", rc);
  109. byte []! in ExHeap buf = new[ExHeap] byte[512];
  110. //string str = null;
  111. int count = 0;
  112. int lastBlock = -1;
  113. while (!done) {
  114. //Socket.Select(listenList, null, null, 1000);
  115. if (s.Poll(1000000, SelectMode.SelectRead)) {
  116. rc = s.Receive(reply);
  117. if (verboseMode) Console.WriteLine("Receive rc={0}", rc);
  118. if (rc >= 4) {
  119. TftpHdr rh = new TftpHdr(reply, 0);
  120. //Console.WriteLine("Opcode {0} Arg {1} rc={2} curPos={3}", rh.Opcode, rh.Arg, rc, curPos);
  121. if (rh.Arg == lastBlock)
  122. Console.WriteLine(" duplicate block? block ="+rh.Arg);
  123. lastBlock = rh.Arg;
  124. if (rh.Opcode == TftpOpcode.DATA) {
  125. if (!verboseMode) {
  126. Console.Write(".");
  127. if (count++ > 50) {
  128. count = 0;
  129. Console.Write("\n");
  130. }
  131. }
  132. else {
  133. //str = Encoding.ASCII.GetString(reply, 4, rc-4);
  134. //Console.WriteLine("pos="+curPos+" str="+str);
  135. //str = null;
  136. }
  137. if (persistHandle != null) {
  138. Bitter.FromByteArray(buf,0,rc-4,reply,4);
  139. persistHandle.SendWrite(buf,0,curPos,rc-4);
  140. switch receive {
  141. case persistHandle.AckWrite( _buf, bytesWritten, error) :
  142. buf = _buf;
  143. curPos = rh.Arg * 512;
  144. break;
  145. case persistHandle.ChannelClosed() :
  146. Console.WriteLine("File handle closed. Quitting");
  147. delete persistHandle;
  148. return null;
  149. break;
  150. case unsatisfiable:
  151. Console.WriteLine("receive is unsatisfiable. Quitting");
  152. delete persistHandle;
  153. return null;
  154. break;
  155. }
  156. }
  157. }
  158. // Build new ack packet - acts as REQ for next block
  159. hdr.Opcode = TftpOpcode.ACK;
  160. hdr.Arg = rh.Arg;
  161. hdr.Marshal(request, 0);
  162. len = 4;
  163. }
  164. if (rc < 512 + 4) done = true;
  165. }
  166. else {
  167. //Console.WriteLine("poll for data failed!");
  168. //return null;
  169. }
  170. rc = s.Send(request, len, SocketFlags.None);
  171. if (verboseMode)Console.WriteLine("Sent {0} {1} rc {2}", hdr.Opcode, hdr.Arg, rc);
  172. //Thread.Sleep(1000);
  173. }
  174. if (persistHandle != null) {
  175. Console.WriteLine("Closing EP handle via delete");
  176. delete persistHandle;
  177. }
  178. delete buf;
  179. return null;
  180. }
  181. public string Put(string! filename, string localName)
  182. {
  183. TftpHdr hdr = new TftpHdr();
  184. byte[] request;
  185. byte[] reply = new byte[8192];
  186. byte []! in ExHeap buf;
  187. FileContract.Imp fileHandle = null ;
  188. int len;
  189. int rc;
  190. long fileLength = 0;
  191. ErrorCode errorOut;
  192. if (null != localName) {
  193. DirectoryServiceContract.Imp! rootNS = DirectoryService.NewClientEndpoint();
  194. FileAttributesRecord record;
  195. bool ok = FileUtils.GetAttributes(localName, rootNS, out record, out errorOut);
  196. delete rootNS;
  197. if (!ok) {
  198. Console.WriteLine("Unable to open file ({0}) for send. reason:{1}",
  199. localName, SdsUtils.ErrorCodeToString(errorOut)
  200. );
  201. return null;
  202. }
  203. fileLength = record.FileSize;
  204. fileHandle = FileUtils.OpenFile(localName);
  205. if (null == fileHandle) {
  206. Console.WriteLine("Unable to open file "+localName+" for send");
  207. return null;
  208. }
  209. }
  210. request = new byte[4 + 512];
  211. len = BuildRequest(request, TftpOpcode.WRQ, filename);
  212. int pos = 0;
  213. bool done = false;
  214. rc = s.Send(request, len, SocketFlags.None);
  215. Console.WriteLine("Sent WRQ rc={0}", rc);
  216. buf = new[ExHeap] byte[512];
  217. int threshold = 20;
  218. int waitCount = 0;
  219. Console.WriteLine(" file size =" + fileLength);
  220. while (!done) {
  221. //Socket.Select(listenList, null, null, 1000);
  222. if (s.Poll(100000, SelectMode.SelectRead)) {
  223. rc = s.Receive(reply);
  224. Console.WriteLine("Receive rc={0}", rc);
  225. if (rc >= 4) {
  226. TftpHdr rh = new TftpHdr(reply, 0);
  227. Console.WriteLine("PUT: Opcode {0} Arg {1}", rh.Opcode, rh.Arg);
  228. if (rh.Opcode == TftpOpcode.ACK) {
  229. int datalen;
  230. int error;
  231. long bytesRead;
  232. Console.WriteLine("ACK for block {0}, pos={1}", rh.Arg,pos);
  233. waitCount = 0;
  234. if (pos >= fileLength) {
  235. Console.WriteLine(" here");
  236. bytesRead = 0;
  237. }
  238. else {
  239. if (fileHandle == null)
  240. throw new Exception("fileHandle is null when I want to SendRead");
  241. fileHandle.SendRead(buf, 0, pos, 512);
  242. fileHandle.RecvAckRead(out buf, out bytesRead, out error);
  243. if (error != 0) DebugStub.Break();
  244. // If we get an ack we can send the next block
  245. pos = (rh.Arg+1) * 512;
  246. }
  247. // Build new DATA packet
  248. hdr.Opcode = TftpOpcode.DATA;
  249. hdr.Arg = rh.Arg;
  250. hdr.Arg++;
  251. hdr.Marshal(request, 0);
  252. datalen = Math.Min(512, (int)bytesRead);
  253. if (datalen < 512) done = true;
  254. //Encoding.ASCII.GetBytes(contents, pos, datalen, request, 4);
  255. Bitter.ToByteArray(buf,0,datalen,request,4);
  256. len = 4 + datalen;
  257. }
  258. else {
  259. Console.WriteLine("NOT AN ACK!\n");
  260. DebugStub.Break();
  261. }
  262. }
  263. rc = s.Send(request, len, SocketFlags.None);
  264. Console.WriteLine("Sent {0} {1} rc {2}", hdr.Opcode, hdr.Arg, rc);
  265. }
  266. else {
  267. Console.WriteLine("Waiting.");
  268. waitCount++;
  269. if (waitCount > threshold) {
  270. Console.WriteLine (" exceeded timeout threshold");
  271. done = true;
  272. break;
  273. }
  274. }
  275. //Thread.Sleep(1000);
  276. }
  277. Console.WriteLine("Done");
  278. delete buf;
  279. if (fileHandle != null)
  280. delete fileHandle;
  281. return null;
  282. }
  283. private static IPAddress GetServerAddress(string server)
  284. {
  285. try {
  286. return IPAddress.Parse(server);
  287. }
  288. catch {
  289. }
  290. try {
  291. IPHostEntry he = Dns.GetHostByName(server);
  292. return he.AddressList[0];
  293. }
  294. catch {
  295. }
  296. return null;
  297. }
  298. private static void Usage()
  299. {
  300. Console.WriteLine("Usage: tftpclient <server> [-i] <put|get> <getfilename> [ <putfilename> ]");
  301. }
  302. /// <summary>
  303. /// The main entry point for the application.
  304. /// </summary>
  305. public static int Main(string[]! args)
  306. {
  307. bool verboseMode = false;
  308. String localName, remoteName;
  309. if (args.Length < 4 || args.Length > 6) {
  310. Usage();
  311. return 1;
  312. }
  313. IPAddress server = GetServerAddress(args[1]);
  314. if (server == null) {
  315. Console.WriteLine("Could not find server : {0}", args[1]);
  316. return 2;
  317. }
  318. int pos =2;
  319. if (args[pos] == "-v") {
  320. verboseMode = true;
  321. pos++;
  322. }
  323. bool doGet;
  324. switch (args[pos]) {
  325. case "get":
  326. doGet = true;
  327. break;
  328. case "put":
  329. doGet = false;
  330. break;
  331. default:
  332. Usage();
  333. return -1;
  334. }
  335. pos++;
  336. remoteName = (!)args[pos];
  337. pos++;
  338. localName = null;
  339. if (pos >= args.Length) {
  340. Console.WriteLine("no destination given");
  341. }
  342. else {
  343. localName = args[pos];
  344. }
  345. Console.WriteLine("doGet="+doGet+" src="+remoteName+" dest="+localName);
  346. TftpClient tftpClient = new TftpClient(server);
  347. if (doGet) {
  348. string contents = tftpClient.Get(remoteName,localName,verboseMode);
  349. if (verboseMode) Console.WriteLine("Contents:\n{0}", contents);
  350. }
  351. else {
  352. //put
  353. tftpClient.Put(remoteName,localName);
  354. }
  355. return 0;
  356. } // end Main
  357. } // end class TftpClient
  358. } // end namespace Microsoft.Singularity.Shell