In this assignment, you’ll create and export a class that attaches
to a socket interface that presents a stream.Readable
-compatible
interface to read a stream of binary network data and parse out
Ethernet frames as they occur, handling both the DIX Ethernet II
and IEEE 802.3 formats.
Ethernet frame addressing, being a data link layer protocol, uses a point-to-point addressing scheme called the media access control (MAC) addressing, a hardware-based addressing scheme that assigns a unique identifier to each network interface controller (NIC), usually available burned into the NIC’s firmware.
Assigned | POSTPONED |
Office hours | By appointment |
Assignment Due | POSTPONED |
Ethernet lives on layer 2 (Data Link) of the layered network model,
but is transmitted over layer 1 (Physical). On the Physical layer,
Ethernet packets are transmitted over transmission media separated
by an inter-packet gap of minimum 12 bytes (octets). When designed, this
gap was intended to provide a delay between packets; now, however, a
12 byte gap provides minimal time delay, and acts simply as a separation
between packets. Because of this, in some cases, that gap is now reduced
to 8 bytes. (In this assignment, to simplify things, we’ll only be concerned
with an inter-packet gap of at least 12 bytes.) Inter-packet gap looks
like idle signal, generally a high voltage level on the wire, or all 1
bits. You can find idle signal by searching for repeated FF
octets.
A new Ethernet packet is signified by a preamble of 7 bytes (octets) of
alternating 1s and 0s, followed by a 1-byte start frame delimiter (SFD)
10101011
. In hexadecimal, this preamble and SFD sequence is
AA AA AA AA AA AA AA AB
.
An Ethernet frame is the layer 2 routing portion of the packet, and begins immediately after the SFD.
So, to find an Ethernet frame in a stream of data, you’ll need to first identify the preamble and SFD. Then, capture from the octet after the SFD until you see 12 or more octets of idle signal. The captured packet can then be trimmed of the additional idle signal and parsed. Use the frame check sequence to ensure that you’ve captured a complete frame.
To complete this assignment, you need to write the body of the parseFrames
function defined and exported from index.js
. In addition, you’ll need to
implement the EthernetSocketProcessor
, an EventEmitter
class that listens
to a socket and parses Ethernet frames as data arrives and emits them in
data
events.
This processing is inherently asychronous. Sockets generally implement the
streams.Readable
interface, so you can look at that class in the Node.js
documentation to get an idea of how data will come into your class.
Once you’ve found the frames that must be parsed, you’ll use your frame parser from assignment A1 to parse the fields out of the frame, so that you can emit a parsed JavaScript object representing the frame’s data.
Your class should extend/implement either events.EventEmitter
or one of the
writable stream
classes (which implement events.EventEmitter
already), and
emit ‘data’ events with the same JavaScript object structure as in Assignment A1
(included below, inside the array, as a reminder) as the event’s message. The
exported function in index.js
should also capture all frames parsed along the
way, and should return a JavaScript Promise
object that resolves with an array
of those parsed frame objects once the socket is closed.
[
{
protocol: (either "Ethernet II" or "IEEE 802.3"),
header: {
destinationMAC: (MAC address binary value as length 6 Buffer),
destination: (MAC Address human-readable text string),
sourceMAC: (MAC address binary value as length 6 Buffer),
source: (MAC Address human-readable text string),
type: (16-bit Unsigned integer value),
length: (16-bit Unsigned integer value, number of payload bytes),
llc: { // only include if relevant to protocol
dsap: (Unsigned Integer),
ssap: (Unsigned Integer),
control: (Unsigned Integer)
},
snap_oui: (MAC OUI binary value as length 3 Buffer, if relevant to protocol)
},
payload: (payload data in binary format as an Buffer with appropriate length),
frame_check: (Integer CRC-32 frame check sequence value),
frame_check_valid: (Boolean, true if computed FCS matches)
},
...
]
While you must make your implementation pass automated tests that
will only use the exported parseFrames
function and the
EthernetSocketProcessor
, class you may want to add additional methods
or classes that assist in finding, segmenting and parsing the stream data.
Each of these functions should be well-tested (repeatably via automation),
so that you can be confident of the accuracy and error-free quality of
your parsing code. Each of these functions should also include relevant
documentation in JSdoc format about why they exist,
including expected inputs and outputs with data types. (Existing code
both here and in Assignment A1 are documented using this format, and some
documentation has already been written for you for the EthernetSocketProcessor
class, which you can use as a specification for what that class should do.)
In this repo, you will find a lib
folder which contains several things
that should be helpful:
ethernet
folder - this is where you should copy the entire assignment A1
project directory so that you can import it as ethernet
into your new projectEthernetSocketProcessor.js
- an empty module where you can create your
socket processor class that emits the appropriate events.In addition to that, you’ll find the main files in the repo root containing helpful tests and starter code:
index.js
- the starting point for your class, which should only import and
export the class for use (the class should be created in its own module in lib
).index.test.js
- a suite of tests that will assess the correctness of your
your implementation.In this assignment, you’ll be working with binary data coming into your
class through a mock network socket which is a subclass of the stream.Readable
class in JavaScript. Data pushed over the this mock socket will be in the form
of binary data Buffer
objects. There are several ways to handle stream
-based data,
which you can learn about
in the Node.js docs on Stream
.
The output of your class should be communicated by emitting JavaScript events
.
You can learn more about working with events
in the Node.js docs on Events
.
Because the output of your class will need to emit events, you may want to try
making your class subclass EventEmitter
,
and then using the event-based reading mode of the input stream.Readable
-compatible class,
adding listeners for relevant events to get the input data from the mock network socket.
As with Assignment A1, in order to get started with the assignment, you’ll want to do the following things:
EventEmitter
index.js
and lib/EthernetSocketProcessor.js
lib/ethernet
folder in this repo. (You may want to exclude the .git
, .vscode
,
and .github
folders from that copy, as it may confuse Visual Studio Code to have those folders at
multiple levels of the repo.)Run the following at the command line from within the project directory (use cd <path>
, replacing
<path>
with the folder path to your project directory, to get there):
nvm use 12.18
npm install
npm test
This assignment will also automatically check your code style for readability. To run those tests at your own command line, you can use:
npm run lint
You must submit your changes as commits to the master
branch on the repository.
Github Classroom will create a pull request on the repository for you, titled
Feedback. As you push your commits on the master branch up to Github, they
will be added to the activity on this pull request.
In addition to the synchronous mechanism of requesting help via office hours appointments, this pull request will be your mechanism for asking questions and requesting help asynchronously during the course of this assignment. I will also use this pull request to provide feedback on your work. I will provide feedback on the completed assignment within a week of the due date of the assignment. If you push your code earlier than the due date, I will try to provide feedback as needed earlier.
I suggest that you push your work to Github as you make commits, and that you make
commits frequently as you work on the assignment. This way, if you have questions,
I will be able to review your work-in-progress and give more relevant answers and
feedback. If you have a question specific to a particular area of the code, note that
you can add comments inline on the pull request by clicking on the Files changed tab
of the pull request, then clicking the little blue +
icon that appears when you hover
over a specific line of code.
I will do my best to respond to questions posed during the course of the assignment with
in a day of the ask. If you want to ask a question or request early feedback, please tag
me in a comment on the pull request: @nihonjinrxs
.
Good luck, and I look forward to seeing what you create!