182 lines
5.6 KiB
C#
182 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;
|
|
}
|
|
}
|
|
}
|