singrdk/base/Applications/Network/UdpGulp/UdpGulp.cs

190 lines
6.3 KiB
C#

////////////////////////////////////////////////////////////////////////////////
//
// 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<UnicodePipeContract.Exp:READY> Stdin;
[OutputEndpoint("data")]
public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
[Endpoint]
public readonly TRef<UdpContract.Imp:Start> 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
}