//////////////////////////////////////////////////////////////////////////////// // // Microsoft Research Singularity // // Copyright (c) Microsoft Corporation. All rights reserved. // // File: TcpBlast.cs // // Note: Simple Singularity test program. // using System; using System.Diagnostics; using System.Net.IP; using Microsoft.SingSharp; using Microsoft.Singularity; using Microsoft.Singularity.Channels; using Microsoft.Singularity.Directory; using NetStack.Contracts; using NetStack.Channels.Public; using Microsoft.Contracts; using Microsoft.SingSharp.Reflection; using Microsoft.Singularity.Applications; using Microsoft.Singularity.Io; using Microsoft.Singularity.Configuration; [assembly: Transform(typeof(ApplicationResourceTransform))] namespace Microsoft.Singularity.Applications.Network { [ConsoleCategory(HelpMessage="Blast TCP data to a ipAddress, port", DefaultAction=true)] internal class Parameters { [InputEndpoint("data")] public readonly TRef Stdin; [OutputEndpoint("data")] public readonly TRef Stdout; [Endpoint] public readonly TRef tcpRef; [StringParameter( "address", Mandatory=true, Position=0, HelpMessage="IP Address to receive from")] internal string address; [LongParameter( "port", Mandatory=true, Position=1, HelpMessage="port to gulp from ")] internal long port; [LongParameter( "numBytes", Mandatory=true, Position=2, HelpMessage="Total bytes to send")] internal long numBytes; [LongParameter( "chunkSize", Mandatory=true, Position=3, HelpMessage="Chunks size to send")] internal long chunkSize; reflective internal Parameters(); internal int AppMain() { return TcpBlast.AppMain(this); } } public class TcpBlast { private const string RepeatPattern = "Here is a repeating string of text that serves as content. "; public static int Blast([Claims] TcpConnectionContract.Imp:ReadyState! tcpConn, IPv4 address, ushort port, uint numBytes, uint chunkSize) { Console.WriteLine("TcpBlast to {0} at port {1} for {2} bytes in {3}-byte chunks", address, port, numBytes, chunkSize); Console.Write("Connecting..."); try { // Try to connect to the remote host tcpConn.SendConnect((uint)address, port); switch receive { case tcpConn.CouldNotConnect(TcpError error) : Console.WriteLine("Failed to connect: TcpError = " + System.Net.Sockets.TcpException.GetMessageForTcpError(error)); delete tcpConn; return -1; break; case tcpConn.OK() : // success; break; case tcpConn.ChannelClosed() : // how rude Console.WriteLine("Netstack channel closed unexpectedly"); delete tcpConn; return -1; break; } Console.WriteLine("Connected"); byte[] in ExHeap buf; uint bytesLeft = numBytes, patternLength = (uint)RepeatPattern.Length; while (bytesLeft > 0) { uint thisPass = chunkSize < bytesLeft ? chunkSize : bytesLeft; buf = new[ExHeap] byte[thisPass]; for (uint i = 0; i < thisPass; i++) { buf[(int)i] = (byte)RepeatPattern[(int)i % (int)patternLength]; } tcpConn.SendWrite(buf); switch receive { case tcpConn.OK() : break; case tcpConn.CantSend() : Console.WriteLine("Connection closed unexpectedly"); delete tcpConn; return -1; break; } bytesLeft -= thisPass; } tcpConn.SendClose(); delete tcpConn; Console.WriteLine("Done"); } catch (Exception e) { Console.WriteLine("Unexpected exception: {0}", e); } return 0; } public static void Usage() { Console.WriteLine("tcpgulp "); } internal static int AppMain(Parameters! config) { IPv4 host; try { host = IPv4.Parse(config.address); } catch (FormatException e) { Console.WriteLine("{0}: {1}", e, config.address); return -1; } if (config.port > 65536 || config.port < 0) { Console.WriteLine("Port number out of range: {0}", config.port); return -1; } ushort port = (ushort) config.port; uint numBytes = (uint) config.numBytes; uint chunkSize = (uint) config.chunkSize; TcpContract.Imp tcpConn = (config.tcpRef).Acquire(); if (tcpConn == null) { Console.WriteLine("Could not initialize TCP endpoint."); return 1; } tcpConn.RecvReady(); TcpConnectionContract.Imp! connImp; TcpConnectionContract.Exp! connExp; TcpConnectionContract.NewChannel(out connImp, out connExp); tcpConn.SendCreateTcpSession(connExp); connImp.RecvReady(); delete tcpConn; return Blast(connImp, host, port, numBytes, chunkSize); } } // end class TcpBlast }