//////////////////////////////////////////////////////////////////////////////// // // Microsoft Research Singularity // // Copyright (c) Microsoft Corporation. All rights reserved. // // File: TcpBlast.cs // // Note: Simple Singularity test program. // using System; using System.Net; using System.Net.Sockets; using System.Threading; using System.Collections; #if SINGULARITY using Microsoft.Contracts; using System.IO; using System.Runtime.InteropServices; using Microsoft.SingSharp; using Microsoft.Singularity; using Microsoft.Singularity.Channels; 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))] #endif namespace Microsoft.Singularity.Applications.Network { #if SINGULARITY [ConsoleCategory(HelpMessage="BlastServer 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; [LongParameter( "port", Mandatory=true, Position=0, HelpMessage="port to gulp from ")] internal long port; [LongParameter( "numBytes", Mandatory=true, Position=1, HelpMessage="Total bytes to send")] internal long numBytes; [LongParameter( "chunkSize", Mandatory=true, Position=2, HelpMessage="Chunks size to send")] internal long chunkSize; reflective internal Parameters(); internal int AppMain() { return BlastServer.AppMain(this); } } #endif public class BlastServer { /////////////////////////////////////////////////////////////////////// // Constants private const int WorkerThreads = 32; private const int MaxWorkItems = 32 * WorkerThreads; private const string RepeatPattern = "Here is a repeating string of text that serves as content. "; /////////////////////////////////////////////////////////////////////// // class variables ushort port; uint numBytes; uint chunkSize; byte[] chunkBuffer; ThreadPool threadPool; private void DispatchRequest(object dispatchObject) { Console.WriteLine(dispatchObject as string); Console.WriteLine("We should Never get here"); #if SINGULARITY DebugStub.Break(); #endif } private void test (object dispatchObject) { Console.Write(dispatchObject as string); } private void Blaster (object sock) { Socket socket = sock as Socket; #if SINGULARITY assert socket != null; #endif int bytesSent = 0; int iterations =0; uint bytesLeft = numBytes, patternLength = (uint)RepeatPattern.Length; try { while (bytesLeft > 0) { uint thisPass = chunkSize < bytesLeft ? chunkSize : bytesLeft; if (thisPass == chunkSize) { socket.Send(chunkBuffer); } else { byte[] thisPassBuffer = new byte[thisPass]; for (uint i = 0; i < thisPass; i++) { thisPassBuffer [(int)i] = (byte)RepeatPattern[(int)i % (int)patternLength]; } socket.Send(thisPassBuffer); } bytesLeft -= thisPass; bytesSent += (int) thisPass; iterations++; } } catch(ArgumentNullException ae) { Console.WriteLine("ArgumentNullException : {0}", ae.ToString()); } catch(SocketException se) { Console.WriteLine("SocketException : {0}", se.ToString()); } catch(Exception e) { Console.WriteLine("Unexpected exception : {0}", e.ToString()); } //Console.WriteLine("Sent {0} bytes in {1} iterations",bytesSent,iterations); socket.Shutdown(SocketShutdown.Both); socket.Close(); Thread.Sleep(2); } private void Listen() { Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.Bind(new IPEndPoint(IPAddress.Any, (int)this.port)); socket.Listen((int)SocketOptionName.MaxConnections); while (true) { Socket s = socket.Accept(); threadPool.QueueUserWorkItem(new ThreadPool.WorkCallback(Blaster), s); } } #if SINGULARITY [NotDelayed] #endif public BlastServer (ushort port, uint numBytes, uint chunkSize) { this.port = port; this.numBytes = numBytes; this.chunkSize = chunkSize; chunkBuffer = new byte[chunkSize]; for (uint i = 0; i < chunkSize; i++) { chunkBuffer [(int)i] = (byte)RepeatPattern[(int)i % (int)RepeatPattern.Length]; } Console.WriteLine("BlastServer listening on port {0} for {1} bytes in {2}-byte chunks", port, numBytes, chunkSize); threadPool = new ThreadPool( WorkerThreads, MaxWorkItems, new ThreadPool.WorkCallback(DispatchRequest) ); #if blee for (int i=0; i < 50 ; i++) { for (int j = 0; j < 40; j++) { bool isFull = threadPool.QueueUserWorkItem(new ThreadPool.WorkCallback(test), "."); while (isFull) { Thread.Sleep(2); isFull = threadPool.QueueUserWorkItem(new ThreadPool.WorkCallback(test), "yes\n"); } } Thread.Sleep(300); } #endif } public static void Usage() { Console.WriteLine("blastserver "); } public void Shutdown() { threadPool.Shutdown(); } #if SINGULARITY internal static int AppMain(Parameters! config) { 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; BlastServer bs = new BlastServer( port, numBytes, chunkSize); bs.Listen(); bs.Shutdown(); return 0; } #else public static int Main(string[] /*!*/ args) { int start = -1; if (args.Length < 4 + start) { Usage(); return 1; } ushort port; try { port = UInt16.Parse(args[1+start]); } catch (FormatException) { Console.WriteLine("Malformed port number: {0}", args[1+start]); return -1; } catch (OverflowException) { Console.WriteLine("Port number out of range: {0}", args[1+start]); return -1; } uint numBytes; try { numBytes = UInt32.Parse(args[2+start]); } catch (FormatException) { Console.WriteLine("Malformed number of bytes: {0}", args[2+start]); return -1; } catch (OverflowException) { Console.WriteLine("Byte count out of range: {0}", args[2+start]); return -1; } uint chunkSize; try { chunkSize = UInt32.Parse(args[3+start]); } catch (FormatException) { Console.WriteLine("Malformed chunk size: {0}", args[3+start]); return -1; } catch (OverflowException) { Console.WriteLine("Chunk size out of range: {0}", args[3+start]); return -1; } BlastServer bs = new BlastServer( port, numBytes, chunkSize); bs.Listen(); bs.Shutdown(); return 0; } #endif } // end class TcpBlast }