URL
https://opencores.org/ocsvn/etherlab/etherlab/trunk
Subversion Repositories etherlab
[/] [etherlab/] [trunk/] [net/] [EtherSocket/] [src/] [EtherSocket.cs] - Rev 2
Compare with Previous | Blame | View Log
/******************************************************************************* ETHERLAB - FPGA To C# To LABVIEW Bridge ******************************************************************************** ** Copyright (C)2012 Mathias Hörtnagl <mathias.hoertnagl@gmail.com> ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/using System;using System.Collections.Generic;using System.Threading;using PcapDotNet.Core;using PcapDotNet.Packets;using PcapDotNet.Packets.Ethernet;namespace EtherLab{/// <summary>/// A socket for EtherLab communication.////// <para>/// Sending////// To send data, first update any channel's data with <see cref="update()"/>./// Subsequently call <see cref="send()"/> to send the updated EtherLab/// packet. If <see cref="update()"/> isn't invoked at least once,/// <see cref="send()"/> will NOT send the packet, as there is no updated/// data available./// <example>/// <code>/// /**/// * Create a new instance of EtherSocket with default/// * destination MAC. The first parameter identifies the/// * network device to select./// *//// EtherSocket es = new EtherSocket(0, "00:1f:16:01:95:a5");////// // Update data for channel H and B./// es.update(EChannel.CHANNEL_H, 0x1234);/// es.update(EChannel.CHANNEL_B, 0x4321);////// // Send the updated packet./// es.send();/// </code>/// </example>/// </para>////// <para>/// Receiving////// EtherSocket starts a new Thread automatically for the reception process./// Data is read constatntly from the networ device./// To read a channel's current data chunk, invoke <see cref="read()"/>.////// NOTE: There is no locking mechanism, to circumvent reading data while/// new data is read from the network device./// <example>/// <code>/// /**/// * Create a new instance of EtherSocket with default/// * destination MAC. The first parameter identifies the/// * network device to select./// *//// EtherSocket es = new EtherSocket(0, "00:1f:16:01:95:a5");////// ushort data;////// // Read data of channel H;/// data = es.read(EChannel.CHANNEL_H);/// </code>/// </example>/// </para>/// </summary>public sealed class EtherSocket{/// <summary>/// Packet receiver filter. Capture packages with EtherType = 0x0000/// and with a Version 2 field only./// </summary>private const String RCV_FILTER= "(ether[12:2] = 0x0000) and (ether[14] = 0x02)";private LivePacketDevice device;private PacketCommunicator com;private PacketBuilder builder;private EtherLabLayer sendLayer;private EtherLabLayer receiveLayer;private Thread receiverThread;/// <summary>/// Creates a new EtherSocket with "00:0a:35:00:00:00" as a default/// destination MAC./// </summary>/// <param name="deviceId">The integer ID of the network device.</param>/// <param name="srcMAC">The source MAC address.</param>public EtherSocket(int deviceId, String srcMAC): this(deviceId, srcMAC, "00:0a:35:00:00:00"){}/// <summary>/// Creates a new EtherSocket./// </summary>/// <param name="deviceId">The integer ID of the network device.</param>/// <param name="srcMAC">The source MAC address.</param>/// <param name="dstMAC">The destination MAC address.</param>public EtherSocket(int deviceId, String srcMAC, String dstMAC){IList<LivePacketDevice> allDevices = LivePacketDevice.AllLocalMachine;if ( (allDevices.Count == 0) || (allDevices.Count < deviceId) ){return;}device = allDevices[deviceId];com = device.Open(56, PacketDeviceOpenAttributes.Promiscuous, 1000);// Filter packages.using (BerkeleyPacketFilter filter = com.CreateFilter(RCV_FILTER)){com.SetFilter(filter);}EthernetLayer ethernetLayer = new EthernetLayer{Source = new MacAddress(srcMAC),Destination = new MacAddress(dstMAC)};sendLayer = new EtherLabLayer();builder = new PacketBuilder(ethernetLayer, sendLayer);// Start receiver thread.receiverThread = new Thread(this.receive);receiverThread.Start();}/// <summary>/// Update channel data and set channel flag. Call send() to send/// the updated data in a new packet./// </summary>/// <param name="channel">The channel to be updated.</param>/// <param name="channelData">The new data for that channel.</param>public void update(EChannel channel, ushort channelData){sendLayer.update(channel, channelData);}/// <summary>/// Sends the current EtherLab packet and resets the channel/// flags to 0. A packet is sent only if at least one channel/// flag is set./// </summary>public void send(){if (sendLayer.pendingSendData()){com.SendPacket(builder.Build(DateTime.Now));sendLayer.reset();}}/// <summary>/// Receive a single packet. Packet data can be read with <see cref="read()"/>./// </summary>private void receive(){com.ReceivePackets(0, PacketHandler);}/// <summary>/// Packet reception callback./// </summary>/// <param name="packet">The received packet.</param>private void PacketHandler(Packet packet){EtherLabDatagram etherLabPacket= new EtherLabDatagram(packet.Buffer, EthernetDatagram.HeaderLength, 18);receiveLayer = (EtherLabLayer) etherLabPacket.ExtractLayer();}/// <summary>/// Read data for a channel from current received packet. If no packet/// is available yet, this function returns 0./// </summary>/// <param name="channel">The channel to be read from.</param>/// <returns>The current channel data.</returns>public ushort read(EChannel channel){return (receiveLayer != null) ? receiveLayer.read(channel) : ushort.MinValue;}}}
