singrdk/base/Services/NetStack/Runtime/UDPModule.cs

181 lines
5.6 KiB
C#

///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Netstack / Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: UdpModule.cs
//
// Note:
//
// #define DEBUG_UDP
using NetStack.Common;
using System;
using System.Collections;
using System.Diagnostics;
#if SINGULARITY
using Microsoft.Singularity;
#else
using System.Net;
#endif
using System.Net.IP;
using Drivers.Net;
using NetStack.Protocols;
namespace NetStack.Runtime
{
public class UdpModule : IProtocol
{
protected IProtocol ip;
public UdpModule()
{
}
// INetModule interfaces
// ---------------------
string INetModule.ModuleName { get { return "UDP"; } }
ushort INetModule.ModuleVersion { get { return 0x01; } } // 0.1
private bool started = false;
public bool StartModule()
{
Debug.Assert(started == false);
started = true;
ip = Core.Instance().GetProtocolByName("IP");
return ip != null;
}
public bool StopModule()
{
return true;
}
public bool DestroyModule()
{
return true;
}
public bool Initialize(ProtocolParams parameters)
{
Core.Instance().RegisterProtocol(this);
return true;
}
public ushort GetProtocolID()
{
return (ushort)IPFormat.Protocol.UDP;
}
public Session CreateSession()
{
UdpSession s = new UdpSession(this);
Core.Instance().RegisterSession(this, s);
return s;
}
public UdpSession CreateUnboundSession()
{
UdpSession s = new UdpSession(this);
Core.Instance().RegisterSession(this, s);
return s;
}
public UdpSession! CreateBoundSession(IPv4 localAddress,
ushort localPort,
IPv4 remoteAddress,
ushort remotePort)
{
UdpSession s = new UdpSession(this);
Core.Instance().RegisterSession(this, s);
s.BindEndPoints(localAddress, localPort,
remoteAddress, remotePort);
return s;
}
[ Conditional("DEBUG_UDP") ]
private static void DebugPrint(string format, params object [] args)
{
Core.Log(format, args);
}
public NetStatus OnProtocolReceive(NetPacket! packet)
{
DebugPrint("Received UDP packet!\n");
UdpFormat.UdpHeader udpHeader = new UdpFormat.UdpHeader();
if (UdpFormat.ReadUdpHeader(packet, out udpHeader) == false) {
DebugPrint("UDP session received unreadable packet.\n");
return NetStatus.Code.PROTOCOL_DROP_ERROR;
}
IPFormat.IPHeader! ipHeader = (IPFormat.IPHeader!) packet.OverlapContext;
if (udpHeader.checksum != 0 &&
UdpFormat.IsChecksumValid(ipHeader,udpHeader, packet) == false)
{
DebugPrint("UDP checksum failed. NO cigar and NO packet!");
return NetStatus.Code.PROTOCOL_DROP_CHKSUM;
}
packet.OverlapContext = ipHeader;
ArrayList udpSessions = Core.Instance().GetSessions(this);
if (udpSessions == null) {
DebugPrint("No UDP Sessions\n");
return NetStatus.Code.PROTOCOL_DROP_ERROR;
}
DebugPrint("Packet : Source {0}:{1} Destination {2}:{3}\n",
ipHeader.Source, udpHeader.srcPort,
ipHeader.Destination, udpHeader.dstPort);
lock (udpSessions.SyncRoot) {
foreach (UdpSession! u in udpSessions) {
DebugPrint("Session : Source {0}:{1} Destination {2}:{3}\n",
u.RemoteAddress, u.RemotePort,
u.LocalAddress, u.LocalPort);
// Match conditions
//
// Bound remote port is zero (not-specified)
// or matches exactly Bound remote IP is Any
// (not-specified) or matches exactly
if ((u.RemoteAddress == IPv4.Any ||
u.RemoteAddress == ipHeader.Source) &&
(u.RemotePort == 0 ||
u.RemotePort == udpHeader.srcPort) &&
(u.LocalAddress == IPv4.Any ||
u.LocalAddress == ipHeader.Destination) &&
(u.LocalPort == udpHeader.dstPort))
{
DebugPrint("Delivered to UDP session\n");
return u.OnReceive(this, packet, udpHeader);
}
}
}
return NetStatus.Code.PROTOCOL_DROP_ERROR;
}
public NetStatus OnProtocolSend(NetPacket! pkt)
{
return ip.OnProtocolSend(pkt);
}
public NetStatus SetProtocolSpecific(ushort opcode, byte[]! data)
{
return NetStatus.Code.PROTOCOL_OK;
}
public NetStatus GetProtocolSpecific(ushort opcode, out byte[] data)
{
data = null;
return NetStatus.Code.PROTOCOL_OK;
}
}
}