Class: Ethernet::FrameSocket
- Inherits:
-
Object
- Object
- Ethernet::FrameSocket
- Defined in:
- lib/ethernet/frame_socket.rb
Overview
Wraps an Ethernet socket and abstracts away the Ethernet II frame.
Instance Method Summary collapse
-
#close ⇒ Object
Closes the underlying socket.
-
#connect(mac_address) ⇒ Object
Sets the destination MAC address for future calls to send.
-
#initialize(raw_socket_or_device, ether_type, mac_address = nil) ⇒ FrameSocket
constructor
Creates a wrapper around a raw Ethernet socket.
-
#recv(buffer_size = 4096) ⇒ Object
Receives an Ethernet II frame.
-
#recv_from(buffer_size = 4096) ⇒ Object
Receives an Ethernet II frame.
-
#send(data, send_flags = 0) ⇒ Object
Sends an Ethernet II frame.
-
#send_to(mac_address, data, send_flags = 0) ⇒ Object
Sends an Ethernet II frame.
Constructor Details
#initialize(raw_socket_or_device, ether_type, mac_address = nil) ⇒ FrameSocket
Creates a wrapper around a raw Ethernet socket.
Args:
raw_socket_or_device:: a raw Ethernet socket or a string containing an
Ethernet device name
ether_type:: 2-byte Ethernet packet type number
mac_address:: 6-byte MAC address for the Ethernet socket (optional if
raw_socket_or_device is an Ethernet device name)
Raises:
RuntimeError:: if mac isn't exactly 6-bytes long
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/ethernet/frame_socket.rb', line 17 def initialize(raw_socket_or_device, ether_type, mac_address = nil) check_mac mac_address if mac_address if raw_socket_or_device.respond_to? :to_str @source_mac = mac_address || Ethernet::Devices.mac(raw_socket_or_device) @socket = RawSocketFactory.socket raw_socket_or_device, ether_type else raise 'MAC address needed with raw socket' unless mac_address @source_mac = mac_address.dup @socket = raw_socket_or_device end @dest_mac = nil @ether_type = [ether_type].pack('n') end |
Instance Method Details
#close ⇒ Object
Closes the underlying socket.
46 47 48 |
# File 'lib/ethernet/frame_socket.rb', line 46 def close @socket.close end |
#connect(mac_address) ⇒ Object
Sets the destination MAC address for future calls to send.
Args:
mac:: 6-byte MAC address for the Ethernet socket
Raises:
RuntimeError:: if mac isn't exactly 6-bytes long
40 41 42 43 |
# File 'lib/ethernet/frame_socket.rb', line 40 def connect(mac_address) check_mac mac_address @dest_mac = mac_address end |
#recv(buffer_size = 4096) ⇒ Object
Receives an Ethernet II frame.
Args:
buffer_size:: optional maximum packet size argument passed to the raw
socket's recv method
Returns the data and the source MAC address in the frame.
This will discard incoming frames that don’t match the MAC address that the socket is connected to, or the Ethernet packet type.
88 89 90 91 92 93 94 |
# File 'lib/ethernet/frame_socket.rb', line 88 def recv(buffer_size = 4096) raise "Not connected" unless @dest_mac loop do data, mac_address = recv_from buffer_size return data if @dest_mac == mac_address end end |
#recv_from(buffer_size = 4096) ⇒ Object
Receives an Ethernet II frame.
Args:
buffer_size:: optional maximum packet size argument passed to the raw
socket's recv method
Returns the data in the frame.
This will discard incoming frames that don’t match the MAC address that the socket is connected to, or the Ethernet packet type.
106 107 108 109 110 111 112 113 114 |
# File 'lib/ethernet/frame_socket.rb', line 106 def recv_from(buffer_size = 4096) loop do packet = @socket.recv buffer_size next unless packet[12, 2] == @ether_type # The last part of the condition accepts multicast packets. next if packet[0, 6] != @source_mac && packet.unpack('C').first & 1 == 0 return packet[14..-1], packet[6, 6] end end |
#send(data, send_flags = 0) ⇒ Object
Sends an Ethernet II frame.
Args:
data:: the data bytes to be sent
Raises:
RuntimeError:: if connect wasn' previously called
57 58 59 60 |
# File 'lib/ethernet/frame_socket.rb', line 57 def send(data, send_flags = 0) raise "Not connected" unless @dest_mac send_to @dest_mac, data, send_flags end |
#send_to(mac_address, data, send_flags = 0) ⇒ Object
Sends an Ethernet II frame.
Args:
mac_address:: the destination MAC address
data:: the data bytes to be sent
Raises:
RuntimeError:: if connect wasn' previously called
70 71 72 73 74 75 76 |
# File 'lib/ethernet/frame_socket.rb', line 70 def send_to(mac_address, data, send_flags = 0) check_mac mac_address padding = (data.length < 46) ? "\0" * (46 - data.length) : '' packet = [mac_address, @source_mac, @ether_type, data, padding].join @socket.send packet, send_flags end |