//////////////////////////////////////////////////////////////////////////////// // // Microsoft Research Singularity // // Copyright (c) Microsoft Corporation. All rights reserved. // // File: UdpGulp.cs // // Note: Simple Singularity test program. // using System; using System.Diagnostics; using System.Net.IP; using System.Threading; using Microsoft.Singularity; using Microsoft.SingSharp; 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="Receive UDP data from a ipAddress, port", DefaultAction = true)] internal class Parameters { [InputEndpoint("data")] public readonly TRef Stdin; [OutputEndpoint("data")] public readonly TRef Stdout; [Endpoint] public readonly TRef udpRef; [LongParameter("t", Mandatory = false, HelpMessage = "Seconds to send packets for", Default = 30)] internal long seconds; [StringParameter("a", Mandatory = false, HelpMessage = "Local address to bind to.", Default = "0.0.0.0")] internal string address; [LongParameter("port", Mandatory = true, Position = 0, HelpMessage = "port to gulp from")] internal long port; reflective internal Parameters(); internal int AppMain() { return UdpGulp.AppMain(this); } } public class UdpGulp { private const int FixedHeaderBytes = 42; // Ether + IP + UDP private static void ReceivePackets( UdpConnectionContract.Imp:ReadyState! udpConn, long totalSeconds ) { int bytesThisRound = 0; DateTime now = DateTime.Now; DateTime epochEnd = now + TimeSpan.FromSeconds(1); DateTime epochStart = now; while (--totalSeconds >= 0) { while (now < epochEnd) { udpConn.SendPollRead((epochEnd - now).Milliseconds); switch receive { case udpConn.NoData() : // No data to read. This doesn't // necessarily mean the connection // is closed. Thread.Yield(); break; case udpConn.Data(uint addr, ushort port2, byte[]! in ExHeap data): bytesThisRound += data.Length + FixedHeaderBytes; delete data; break; case udpConn.ChannelClosed(): throw new Exception("udpConn channel closed"); } now = DateTime.Now; } TimeSpan delta = now - epochStart; Console.WriteLine( "Duration(s) {0:f2} rate(bps) {1:e3} bps", delta.TotalSeconds, 8.0 * bytesThisRound / delta.TotalSeconds); bytesThisRound = 0; epochStart = DateTime.Now; epochEnd = epochStart + TimeSpan.FromSeconds(1); } } public static int Gulp([Claims] UdpConnectionContract.Imp:ReadyState! udpConn, IPv4 address, ushort port, long totalSeconds) { Console.WriteLine("UdpGulp({0}, {1})", address, port); try { // Bind local endpoint udpConn.SendBindLocalEndPoint((uint)address, port); switch receive { case udpConn.OK() : // success; Console.WriteLine("Connected"); break; case udpConn.InvalidEndPoint(ip, rejectedPort) : throw new Exception("udpConn address and port rejected"); case udpConn.ChannelClosed() : throw new Exception("udpConn channel closed"); } ReceivePackets(udpConn, totalSeconds); Console.WriteLine("Closing connection"); udpConn.SendClose(); } catch (Exception e) { Console.WriteLine("Unexpected exception: {0}", e); } finally { delete udpConn; } return 0; } 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 > 0xffff || config.port < 0) { Console.WriteLine("Port number out of range: {0}", config.port); return -1; } ushort port = (ushort) config.port; UdpContract.Imp udpConn = (config.udpRef).Acquire(); if (udpConn == null) { Console.WriteLine("Could not initialize TCP endpoint."); return 1; } Console.WriteLine("Waiting for ready"); udpConn.RecvReady(); UdpConnectionContract.Imp! connImp; UdpConnectionContract.Exp! connExp; UdpConnectionContract.NewChannel(out connImp, out connExp); Console.WriteLine("Creating session"); udpConn.SendCreateUdpSession(connExp); connImp.RecvReady(); delete udpConn; Console.WriteLine("Ready"); return Gulp(connImp, host, port, config.seconds); } } // end class UdpGulp }