Project Report - Networked Software Systems Laboratory

Spring
Distributed
Push-to-talk
2009
Produce a product which enables ad-hoc Push-To-Talk (PTT) voice
communication over unreliable networks between multiple participants
while using reasonable amounts of bandwidth.
Asaf Oren & Gilad Eisenberger
Supervisor: Ittay Eyal
EE Networked
Software Lab,
Technion
Table of Contents
Problem Description ................................................................................................................................................................................................................................ 2
Background ........................................................................................................................................................................................................................................ 2
Goals............................................................................................................................................................................................................................................ 2
What is PTT voice communication? ............................................................................................................................................................................................. 2
Communication Model ...................................................................................................................................................................................................................... 2
Why the internet ......................................................................................................................................................................................................................... 2
Communication Model Assumptions ........................................................................................................................................................................................... 2
Requirements .................................................................................................................................................................................................................................... 3
General ........................................................................................................................................................................................................................................ 3
Joining/Leaving the network ........................................................................................................................................................................................................ 3
Voice & Floor ............................................................................................................................................................................................................................... 3
UX ................................................................................................................................................................................................................................................ 3
Solution ................................................................................................................................................................................................................................................... 4
Overview ........................................................................................................................................................................................................................................... 4
Technologies ...................................................................................................................................................................................................................................... 4
C# .NET ........................................................................................................................................................................................................................................ 4
Networking .................................................................................................................................................................................................................................. 4
Sound API .................................................................................................................................................................................................................................... 5
Technical Aspects .............................................................................................................................................................................................................................. 5
Serialization ................................................................................................................................................................................................................................. 5
Lower-level Network Protocol ..................................................................................................................................................................................................... 5
Multi-threading ........................................................................................................................................................................................................................... 6
Implementation ....................................................................................................................................................................................................................................... 7
Implementation Overview ................................................................................................................................................................................................................. 7
Initial Implementation (Server-Client) ............................................................................................................................................................................................... 8
Server-Client Overview ................................................................................................................................................................................................................ 8
Protocol ..................................................................................................................................................................................................................................... 10
Shared Components .................................................................................................................................................................................................................. 10
Client ......................................................................................................................................................................................................................................... 10
Server ........................................................................................................................................................................................................................................ 11
Distributed Implementation ............................................................................................................................................................................................................ 11
Conclusions from Initial Implementation ................................................................................................................................................................................... 11
Protocol Changes ....................................................................................................................................................................................................................... 12
Generic Client Implementation .................................................................................................................................................................................................. 12
Conclusion ............................................................................................................................................................................................................................................. 15
General ............................................................................................................................................................................................................................................ 15
Problems Solved .............................................................................................................................................................................................................................. 15
Open Issues ..................................................................................................................................................................................................................................... 17
Future Work .................................................................................................................................................................................................................................... 18
Appendix ................................................................................................................................................................................................................................................ 19
User Manual .................................................................................................................................................................................................................................... 19
Problem Description
Background
Goals
Produce a product which enables ad-hoc Push-To-Talk (PTT) voice communication over unreliable
networks between multiple participants while using reasonable amounts of bandwidth.
For our project, we will develop a product to enable PTT voice communication over the internet
network.
What is PTT voice communication?
Push-To-Talk voice communication is a method of communication using an audio technology that
transmits the user’s voice to other users. When the user wishes to transmit, the user then pushes a
button to start transmitting. When the user wishes to stop transmitting, the user simply releases the
button.
In most push-to-talk communications, only one user can transmit at a given time, and while the user is
transmitting, all other users receive his voice communication. This is called half-duplex communications,
and is the type of communication we will focus on in this project.
Communication Model
Why the internet
The internet is the largest communications network available today, and is a great example of how
unreliable networks operate. We believe that a solution that would be capable of meeting our
requirements while communicating over the internet would be able to do so over almost any other
network widely available today.
In addition, the internet is very accessible, and provides an open framework we can easily utilize while
developing our product.
Communication Model Assumptions
All the machines in the network are connected, meaning every computer can communicate directly with
every other computer. The network is unreliable meaning:
1. Messages between computers may be delayed or even completely lost.
2. At any given time, a machine may get disconnected from the network.
Requirements
These are the requirement of the application developed:
General
1. The application should be able support only one instance of itself per machine. Furthermore,
every instance will be controlled by a single user connected to at most one PTT network.
2. The application will use no central service to coordinate communications. The client applications
will directly communicate with each-other
Joining/Leaving the network
3. Joining a network is done by requesting admission from one of the machines connected to that
network
4. Every instance of the application should maintain a list of all the users connected to a network –
After a new user has joined the network, his admission should propagate to all other computers
in the PPT network, and then same goes for when a user leaves the network (gracefully or in
case of disconnections).
5. The application must detect disconnections, and recover from them (no single point of failure).
Voice & Floor
6. When a user wishes to talk to other computers on the network, he must "have the Floor"
(meaning have the singular right to transmit). Only one user on the network can have the floor,
and once achieved the user will remain the sole owner of the floor until he wishes to give it up.
7. The application should be able to receive voice messages from its peers in the network, and play
them. The application should also be able to record and send voice messages to its peers, if the
user has the floor.
UX
8. The user should be able to –
a. Join a network – The application should achieve that with only an IP of a member of the
network supplied by the user.
b. Disconnect from a network
c. Receive voice from the user who currently has the floor.
d. Request the floor – an audio notification should be played upon success and a different
one upon failure.
e. Transmit voice – After a successful request of the floor, voice will be recorded until user
decides to –
f.
Relinquish floor.
Solution
Overview
We will develop a high-level network protocol and define the behavior of the various components in our
system in a way that solves the problem as defined. We intend to develop concepts which will later
allow other solutions to similar problems, or creation of other specific implementations of solutions to
the same problem.
To demonstrate and test the viability of our concepts we will develop an application as a single solution
to the above problem. This application will allow us to evaluate the effectiveness of our developed
concepts, as well as identify possible issues and validate any modification to overcome these issues.
Our specific solution consists of a Windows application using the .Net framework. This application will
use a communications channel to communicate with other instances of the application running on other
computers.
The communications channel will use a custom communications protocol, specifically for our
requirements, which will operate over UDP.
The application will use the standard Windows sound APIs to record sound from a microphone, and play
it to the speakers/headphones when required. Use of a standard sound API allows us to focus our on the
network communications aspect of the development, instead of specific issues related directly to
recording and playing sounds.
Technologies
C# .NET
As mentioned, our Windows application will be developed using the .Net framework in C#. Use of an
existing, extensive framework allows for quicker development, easier debugging, and lets us focus our
efforts on defining the behavior of the application, rather than on getting it to function according to the
definition.
Use of existing libraries for sound, networking, UI and other components, as well as the general
simplicity of the C# language enable rapid development and prototyping of new ideas. Such exploration
proved invaluable in getting everything working correctly together.
Networking
To enable networking in our application, we will develop a custom networking protocol, as well as an
implementation that will communicate using this protocol. We will base the protocol over UDP, as this
low-level protocol is supported across most internet links, and is very widely used.
Using UDP should allow for better networking efficiency during communications that require timely
arrival. Since our sound stream is only relevant within a reasonable amount of time after being
broadcast, reliable delivery is not required. Instead, lost packets can simply be omitted, causing a short
hiccup in sound playback on the receiving end.
In addition, UDP is significantly easier for performing NAT traversal than TCP or other lower-level
protocols. This allows for easier connections between computers behind firewalls or routers. Since the
great majority of internet users are behind such devices, this is a significant feature.
Sound API
For sound recording and playback, we will use the WaveIn and WaveOut Windows API calls. This is part
of the standard Windows sound functionality, and is available on a wide range of computers. Since the
application being developed is mostly to demonstrate the feasibility of our concepts, we will not focus
on how audio data is captured. Various implementations might use different methods to acquire this
data but this is no doubt possible, so we’ll simply use the simplest method to do so.
In addition, Speex will be used to compress sound as it travels through the network boundary. Speex is a
public open-source library for compression of sound, mostly voice, specifically designed for VoIP use.
Speex should allow our application to communicate over less efficient network links with greater quality.
In addition, Speex has built-in support for error correction on lost packets, which should allow our
application to cope with communications issues with the minimal loss of sound quality.
Technical Aspects
There are several technical issues that need to be overcome to allow our implementation to function
correctly.
Serialization
It is clear that any implementation will need a way of transmitting data over the networking layer. For
our implementation, we elected to create message objects, which exist in the application. These objects
are created and modified as needed, and then transmitted over the network layer.
In order to transmit objects over such a layer, they need to be serialized into a stream of bytes. The
serialization scheme we propose would consist of two operations, one performed on a message object,
which transforms it to a stream of bytes, and a second, which produces a message object from a stream
of bytes.
In order to ensure messages can be properly deserialized, we will add a short header containing a
message type identifier to the start of each message sent. This will allow the receiving end to identify
the type of any incoming messages.
Lower-level Network Protocol
In order to produce reliable networking, while still retaining the ability to transmit data in a highly
efficient, non-reliable way, we propose producing a lower-level protocol, over which all our
communications will take place.
It is clear such a protocol would need to support both Reliable type messages, as well as Non-Reliable
type messages.
To retain maximum efficiency when transmitting Non-Reliable type messages, we will simply transmit
them as a single UDP datagram. This implementation remains simple, yet should require the least
overhead.
To implement Reliable type messages, we will use Stop and Wait communications between two peers.
To do so, each message is tagged with an integer index, and only the next expected message is
processed by the receiving end. In addition, the receiving side responds to any incoming message with
an ACK message holding the next expected index. When the sender receives an ACK message with the
next index, it knows the receiving side received the last message, and proceeds to the next one.
Since the message index is only applicable to reliable messages, it will be added after the message type
identifier created when serializing the message, to allow the receiving side to identify whether the index
exists using the first bytes of the message.
Header structure for a reliable message:
4 bytes
Message Type
4 bytes
Index
N bytes
Message Contents
Header structure for a non-reliable message:
4 bytes
Message Type
N bytes
Message Contents
This implementation provides a reliable, in-order channel for messages that have this requirement. In
addition, this implementation allows detection of disconnections in the network, when a message
cannot be sent successfully for too long.
Implementing this lower-level networking protocol should allow us to develop our higher-level protocols
with the assumption that messages we select can be reliably delivered in-order, and that any
disconnections are detected within a reasonable amount of time.
Multi-threading
Examining the requirements for our implementation, it is clear that this application will not need to
perform a large amount of time-critical calculations. Since there is no performance requirement for
parallel calculation, or any long operation that might cause the UI to be unresponsive, use of multithreading is not required.
To keep things simple, we will keep the number of threads down to a minimum. Due to the way
Windows Sockets work, one thread is required for handling incoming messages. In addition, the UI
requires a thread of its own. Therefore we require two threads in the application and since both
perform very little processing, it would be perfectly fine if only one was performing operations at a given
time. This should be easy to enforce using locking mechanisms while performing operations.
Implementation
Implementation Overview
The goals of our implementation are to prove the viability of our developed concepts and solution, as
well to assist us in identifying possible issues as we advance. As such, it seems logical that we use our
implementations to learn from while we develop our solution. To do so, we decided to split our
implementation into several phases, using these as validations for our process, as well as providing an
opportunity to rethink decisions as we move along.
Our original plan was to implement our solution in three phases. The initial phase would be to develop a
fully-functioning solution, with the exception that it used a centralized Server for communications, and
all communications would be routed through this Server. As a second phase, we planned to add a
second communications channel directly between Clients, in addition to the one through the Server.
Using this new channel, Clients would coordinate floor possession in a distributed fashion, with the
Server providing routing services for Sound data. For the third phase, we had planned to remove the
Server completely, and modify the Clients to route Sound data between themselves as well, using the
distributed channel developed in the previous phase.
Diagram 1 - Implementation plan
The idea behind the initial phase was to focus on the technical aspects of our solution, such as setting up
sound related infrastructure, as well as developing our lower-level network protocol. After completing
this phase, we would be well prepared to focus solely on developing our concepts and higher-level
protocol. In addition, not implementing any distributed communications during the first phase allows us
to defer selecting a specific distributed topology/protocol to a later phase.
Shortly after completing the first phase of our implementation, and reaching a working application using
a centralized Server, we began to evaluate methods for forming a distributed channel. During our
evaluation, we decided against using a “Gossip” type network, where every Client communicates with
every other Client in the network. Instead, we elected to implement a Tree topology network, where
each Client has one parent, and any number of children.
The main consideration for not using a Gossip network is its poor ability to perform efficient routing of
real-time sound data within the network. Unlike the Gossip network, a tree topology, when structured
correctly, can efficiently share real-time data to all members. This allows easier implementation of our
solution in a way that meets our requirement, and therefore was selected.
When examining how to proceed using the selected network type, we came to the conclusion that
developing a mixed-network implementation using a tree-network to communicate between Clients
would be ineffective. Specifically, maintaining network communications with a centralized Server while
doing so within a tree-topology would require special handling, which would not be required in the third
phase.
Following this decision we decided to modify our implementation plans and convert the existing ServerClient implementation directly to a fully-distributed tree-topology implementation. We believe
removing the former second phase allowed us to avoid developing concepts and adapt our
implementation due to factors that would not be relevant in the final solution.
Our final implementation consists of two implementation phases, first a Server-Client phase, followed by
a fully-distributed phase, as described below:
Diagram 2 - Modified implementation plan
Initial Implementation (Server-Client)
Server-Client Overview
Our initial implementation will consist of two types of applications, a Server application and a Client
application. The Server application will be developed to provide an infrastructure for communications
between multiple Client instances.
This type of asymmetric application topology also creates a distinctly asymmetric protocol. It is clear
that messages sent from a Client to the Server will contain different data than those sent in the opposite
direction. In this asymmetric topology, the Server will be responsible for mediating between Clients,
who do not communicate directly. Since there is only one Server instance in the topology, any decision
made at the Server level can be easily made atomic. By making the Server responsible for all decisions,
Clients become a very thin interface between the UI and the Server, translating the User’s actions to
requests made to the Server, and responses from the Server to UI notifications.
Despite the differences in content communicated between the two types of applications, both still have
3 similar areas of responsibility within each application instance. These are management of Users, The
Floor, and Sound Data. While the responsibilities in each area are different between the Client and
Server applications, there is a correspondence in the type of data processed, resulting in a dependency
between these areas on each of the application types.
In addition, there are areas where symmetry between the Client and Server applications is obvious. Both
types will require an implementation of the lower-level networking protocol we designed. Since this
protocol is symmetric even in the Server-Client implementation, it is clear the same implementation
could be used for both. In addition, code to route messages internally, as well as utility objects, such as
for representing Users, can be shared between the two implementations.
Due to these similarities, we propose a similar high-level design for both the Server and Client
applications. This design, and the similarity between the applications that results in the high-level
structure, should allow easier transitioning to a single, symmetric implementation. This general
structure would consist of 3 components to handle Users, Floor and Sound, as well as a component to
handle lower-level networking, one to route incoming messages, and one to handle outgoing messages.
Diagram 3 - General structure of application in Server-Client implementation
Protocol
The high-level protocol is designed to allow the application to share information between instances. In
this case, messages that are sent from the server carry different information that those sent from
Clients. Below is a list of all message types, grouped by the type of application they are sent from.
Client to Server Messages
Message Type
Connect
Disconnect
Fields
UserName, UserId
UserId
Reliable
Yes
Yes
FloorRequest
FloorReleased
Sound
UserId, RequestId
(none)
Data (byte array)
Yes
Yes
No
Description
Sent when a Client wishes to connect to a Server
Sent when a Client wishes to disconnect from a
Server
Sent when the User would like to request the floor
Sent when the User releases the floor
Sent periodically while the user has the floor,
carrying the sound data recorded in the period
Server to Client Messages
Message Type
AddUser
Fields
User
Reliable
Yes
RemoveUser
UserId
Yes
FloorResponse
UserId, RequestId,
Granted (bool)
UserId
Data (byte array)
Yes
FloorChanged
Sound
Yes
No
Description
Sent to notify a Client that a Client has joined the
network
Sent to notify a Client when a Client leaves the
network
Sent as a response to a FloorRequest message,
detailing the result of the request
Sent to notify the owner of the floor has changed
Sent periodically while a Client has the floor,
carrying the sound data recorded in the period
Shared Components
Messaging Component – This component is a simple implementation of the lower-level networking
protocol described previously.
Topology Manager – This component is responsible for messages going out of each application.
Responsibilities of managing the network topology are focused in this single component, allowing easy
modifications to the network topology if required.
Message Router – This component is responsible for routing incoming messages to the different
components. Since each component handles only certain types of messages, this component is aware of
all message types and all components, and routes messages internally as needed.
Client
In addition to the shared components, each Client will have 3 components to handle each of the 3 main
areas of responsibility.
Users – The component responsible for User data on the Client application is the UserTracker. This
component is responsible for tracking the list of active users provided by the Server, keeping a local copy
up to date, so that it can be displayed to the User.
Floor – The component responsible for Floor data is the FloorTracker. This component is responsible for
both tracking which User currently has the floor, as well as tracking requests for the floor, and their
results.
Sound – The SoundManager component is responsible for Sound data on the Client. This component is
responsible for recording sound data and transmitting it while the Client has the floor and for receiving
and playing incoming sound when another Client has the floor.
Server
The Server application contains most of the logic related to both User management, as well as Floor
possession. First, the Server is responsible for accepting incoming connections, and notifying the
connecting Client of all other Clients, and existing Clients of the new one. Second, the Server tracks the
current owner of the Floor, and handles requests for the floor internally. Whenever the Floor changes,
the Server notifies all connected Clients of the change.
In addition to the shared components, the Server will have 3 components to handle each of the 3 main
areas of responsibility.
Users – the UserManager component is responsible for handling connection and disconnection
messages, as well as tracking the list of connected Users and notifying all Clients whenever a change
occurs.
Floor – the FloorManager component manages Floor possession. This component is responsible for
keeping track of which User currently has the Floor, handling requests for the Floor, and notifying all
Clients when a change occurs.
Sound – the SoundRouter component is solely responsible for routing any sound data arriving from a
Client to all connected Clients.
Distributed Implementation
Conclusions from Initial Implementation
Moving forward from the Server-Client asymmetric design, to a distributed one, it is clear that symmetry
would be required. Since the application should support any number of identical Clients, they would
naturally need to be able to fulfill all positions in the selected topology.
The natural structure for a distributed network transmitting sound data is a tree. Under this structure,
each Client is a node in a tree, and has zero or one parents, and any number of children. Each parent or
child is also a Client application. Speaking in terms taken from the Server-Client implementation, it is
clear each Distributed-Client now serves two roles – it is a Server to its children, and a Client to its
parent.
Using this terminology, it is clear the new symmetric Client will need take on responsibilities of both the
Client and the Server from the previous implementation. Since the components already cover the same
areas of responsibility on both the Server and Client, merging them should take place on a per-area
basis.
Protocol Changes
As mentioned, the protocol is now symmetric, and so each Client needs to be able to send and receive
every type of message. Messages in the modified protocol remain very similar to those in the ServerClient protocol, with minor changes raised by having to manage a topology of Users, instead of simply a
list of Users.
In addition, since messages are routed through the new topology, sending different messages to
different users becomes ineffective. Since the FloorChanged and FloorResponse messages from the
previous protocol are sent in response to the same event, they can easily be combined in this modified
protocol.
Below is a list of all messages in the modified protocol:
Message Type
Connect
Fields
UserName, UserId
Reliable
Yes
Disconnect
UserId
Yes
FloorRequest
UserId, RequestId
Yes
FloorReleased
(none)
Yes
AddUser
User, ParentId
Yes
RemoveUser
UserId
Yes
FloorResponse
UserId, RequestId,
Granted (bool)
Yes
Sound
Data (byte array)
No
Description
Sent from a Client when the client wishes to join
the network as a child of the Client to which the
message was sent
Sent when a Client to its parent when the Client
wishes to disconnect from the network
Sent from a Client to its parent when the User
requests the floor
Routed through the network whenever the floor is
released, to notify all members the floor has been
freed
Sent to notify a Client that a Client has joined the
network, also including who this Client’s parent is
Sent to notify a Client when a Client leaves the
network
Sent as a response to a FloorRequest message,
detailing the result of the request, and routed
through the network to inform all Clients of the
change
Sent periodically while a Client has the floor,
carrying the sound data recorded in the period. This
message is routed through the tree topology to all
members of the network
Generic Client Implementation
As discussed in the overview, the new Distributed-Client implementation’s general structure remains
the same as the Server-Client applications. We will retain the general components which were
previously shared between both the Server and the Client. These will contain the non-area specific
functionality, as they did before. In addition, the 3 area-specific components will need to have extended
responsibilities merged from both the Client and the Server from the previous implementation.
Changes to the shared components should not be significant. The type that represents a User would
need to be expanded to support a tree topology, by adding properties for Parent, Children, etc. In
addition, the TopologyManager component should be expanded to sending messages through the new
topology. The MessagingComponent and MessageRouter do not need to be modified, as the low-level
networking protocol remains the same, as well as the message types used by the area-specific
components.
Diagram 4 - General structure of generic client application
To expand the TopologyManager to support the new functionality, a few new operations would need to
be added. To the existing SendMessage and Broadcast (which send messages to a specific Client and to
all Clients respectively), we would need to add operations that relate to the tree topology. It is clear an
operation for sending a message to the current Client’s parent would be required. This would be used
when a decision regarding an action would need to be delegated to the Client’s parent, such as when a
floor request is made. In addition, an operation which routes a message through the tree topology, that
is, sends it in all directions except the one it arrived from, would be required as well. Routing messages
allows a Client to share information about an event, such as the floor changing, with all Clients that do
not yet have this information. In addition, an operation matching the send-to-parent one needs to be
created for notifying children when an even occurs.
Implementation of the area-specific components remains relatively similar to that of the previous
implementation. As was mentioned, each component now accepts the responsibilities of the Server and
Clients’ components for that area. Each component still only communicates with the same component
on other instances of the Client, requiring each component to only be able to send and receive its own
message types.
As with the previous implementation, the three areas are Users, Floor and Sound.
UserTracker – The UserTracker component is responsible for tracking connected Users/Clients, and the
topology in which they are connected. UserTracker components on the various Clients notify each other
through the tree topology of changes. The UserTracker stores information related to each User (such as
their display name), and makes this information available to other components, as well as the UI.
FloorTracker – The FloorTracker component is responsible for tracking which User currently holds the
floor, as well as making decisions when a request is made to change the floor owner. FloorTracker
components on different instances of the application communicate changes to floor. All instances make
requests from the root of the tree topology, which makes decisions internally and sends responses back
through the topology.
SoundManager – The sound manager is responsible for recording sound while the Client has the floor,
and playing it back while another Client has the floor. Changes to this component are minimal, and only
require adding code to route incoming messages to other Clients in the topology that rely on the current
Client for routing. The component still broadcasts sound while the Client has the floor and plays back
any sound it receives.
Conclusion
General
With our implementation of the solution complete, we are able to evaluate how well it solves our
problem. Through testing of our application both during development, and after, we feel confident our
solution is a practical, simple, and effective solution to the problem.
We have been able to use our application in various scenarios and communicate successfully between
clients with no centralized server. We feel the application meets the requirements of the problem we
set forth to solve. This specific solution acts as a proof-of-concept for the validity of our concepts. We
feel these concepts can be easily adapted into a working product easily.
During our implementation, we encountered many issues and attempted to overcome them as we
moved forward. We feel the majority of issues were solved during the process; however, some issues
were left open.
Problems Solved

Network communications
Our implementation creates an abstraction layer over the basic network protocols available,
allowing our higher-level implementations to operate free of concern for concepts which exist in
the lower-level. We feel our lower-level protocol is simple, flexible (supports reliable and nonreliable messages) and most importantly portable to other solutions.

Serialization
As discussed earlier, we developed code to perform serialization and deserialization of our
message objects to a byte stream before being sent over the network. While Serialization is a
well-solved problem, our requirements of a serialization method that would be both efficient in
time and efficient in the size of the result required we develop our own Serialization scheme. By
creating operations that convert messages to and from byte streams we were able to
significantly streamline the work involved in both the initial development and later
modifications to our higher-level network protocol by simply modifying the message classes.

Reliable, in-order messaging
In order to develop a lower-level reliable protocol we used the well-known Stop and Wait
protocol to transmit messages in a reliable, in-order fashion. While this solution is simple, it
works efficiently in removing the need for handling messages that arrive out-of-order or fail to
arrive. Being able to rely on a reliable, in-order delivery mechanism allowed us to simplify the
higher-level protocols, which required no validation of any kind.

High-efficiency messaging
Another issue which required attention was communications that required high-efficiency
sending, specifically the real-time sound data. Since this data is time-critical, any type of reliable
communications would not be feasible. Instead, the application would need to be able to handle
loss of some of the data, and a non-reliable delivery method should be used. We feel our use of
simple UDP datagrams for this type of communications was an effective solution to the problem
despite its simplicity.

Sound recording and playback
While APIs for recording and playing sounds have long been a standard part of the Windows
operating system, the process of recording and playing sounds is not yet streamlined. Our
application would be required to properly record and play data. While developing our solution,
we encountered several issues with regards to the reliability of recording sound from the
standard Windows APIs. While these issues were mostly due to improper use, fixing the issues
required significant effort, as did verifying they work properly over time. Our eventual
implementation works reliably, however, we only had a limited number of computers to test it
on. As with the rest of our application this code should be considered proof-of-concept only,
and not a reliable solution, even though it appears to work properly.

User Tracking
An integral part of our application would need to be tracking of Users on the network. While the
initial Server-Client implementation only had a simple User list, the final implementation held a
User topology, with links between Users. Maintaining this list across the distributed network
proved challenging. Our higher-level protocol addresses this issue, by defining exactly how
Clients communicate and cooperate in maintaining this topology of Users. As demonstrated, our
application tracks Users as they join and leave the topology, effectively solving the problem.

Floor management
The second integral part of the application is managing Floor possession. While the decisions
relating to handling requests for the Floor, as well as notifying Clients of changes required
attention. Our method of simplifying the issue by assigning a single decision point for Floor
possession proved successful. In addition, the level of abstraction provided by our higher-level
protocol allowed us to easily handle edge cases which we identified only after the initial
implementation. For example, we adapted our solution to be able to notify a connecting Client
of the current Floor owner when the Client connects after Floor possession had been
determined. Also, when a Client disconnects while it has possession of the Floor, it is released
on behalf of the possessing Client.
These adaptations allowed us to create a robust system for tracking and handling requests for
the Floor, which we feel is a perfectly viable solution for any future implementations.

Disconnections
An integral part of maintaining communications over the internet is frequent disconnections. It
is not uncommon for computers to periodically be unable to communicate with some or all
other computers.
As such, a scheme to handle these events was required. For our implementation, we developed
a failure detection mechanism to detect these events, and respond to them by disconnecting
the Client experiencing the failure from the network. The failure detection mechanism detects
failures by tracking attempts at sending reliable messages to peers.
When sending of a reliable message (or receiving of an ACK message) fails a specified number of
times in a row, the peer is declared as disconnected, and the local application responds as
though the peer sent it a disconnect message. This allows the network to continue to operate
normally after a network failure occurs.
Open Issues

NAT Traversal
While we did put consideration into handling NAT traversal in our implementation, specifically
when selecting to use UDP as the lowest-level protocol, this does not pose a complete solution
to the problem. NAT traversal for peer-to-peer applications is considered relatively difficult, and
usually requires a global service to assist in performing the traversal. We consider this an issue
for further work, and did not focus on creating a reliable solution to NAT traversal, and instead
focused on our higher-level protocols. Use of simple UDP connectivity should assist in
translating NAT routers, though under some circumstances traversal using our application might
not be possible natively.

Reconnections
While our solution handles disconnections cleanly, both in detecting them and in responding to
them when they occur, the application makes no attempt to reconnect when a disconnection
occurs. We can think of several solutions to this problem, however implementing a specific
solution does not seem worthwhile. The Client has a list of all existing Clients in the network
before the disconnection; therefore any future implementation wishing to reconnect the User
without prompting him could easily do so. Our solution requires the User to reconnect
manually.

Security
Security is a big issue in all network communications over unsecured networks, especially the
internet. Maintaining reliable security over peer-to-peer connections is difficult as well.
Nevertheless, many existing solutions could be easily used to secure any network
communications, regardless of the way the protocol itself is built. For example, many solutions
for creating secure channels between computers already exist, and can be easily utilized to
secure channels between our Client applications.
We made an early decision that we would consider security at all when designing our protocol.
It is obvious security should be a consideration in every deployed solution; however, since our
application is merely designed to serve as a proof-of-concept, we made a conscious decision to
favor simplicity over security in every aspect of our solution.
When developing and testing our application, we made the assumption all Clients connected to
the network behave according to our defined protocol, and that there are no malicious Users
attempting to cause inconsistencies in data.
Future Work
Overall, we feel the solution and concepts developed in this project are a viable and useful solution to
the problem we defined. These concepts can be easily incorporated as the base for a working
commercial product easily, with little modifications, if any. Therefore, we feel more work on the
concepts of the solution, or even the high-level protocol, are not required. While there are certainly
possible additions to the solution, such as adding text messaging, or private sound recordings that only
reach a single user, they are not required to solve the problem.
Regarding our implementation, as we stated, it is designed as a proof-of-concept, and is far from
complete. Other than the open issues discussed above, further work on the implementation (to ensure
it is robust enough), is required. We do not, however, feel there are any significant problems to be
encountered implementing our solution.
Appendix
User Manual
To start the application, simply run the application executable. There is no installation required.
Once the application starts, the Connection window appears. This window allows you to select whether
you want to start your own network, or connect to an existing one.
If you select to join an existing network, you must enter the IP Address of an existing member of the
network.
You also need to enter a User Name to be displayed when you join the network. In addition, you may
optionally select to change the port numbers used by the application (mostly used for debugging and
testing).
Once you are done entering these settings, click Start to join or start hosting a network.
The main application window appears, showing all members connected.
The image below shows a network with more than one User connected. Note the Users appear in a tree,
illustrating how information is shared between them.
To start talking with other members of the network, when no one else is talking, press the Request
button. If no one is talking, you will get the floor. A “Floor Granted” message appears in the window’s
notification area, and a sound notification is played. At this point, the application begins recording
through your microphone, and all other members of the network will be able to hear you speak.
Note the owner of the floor is marked in red so everyone can know who is currently talking.
When you’re done talking, click the Relinquish button to stop recording. The floor will be released for
others to request.
If you attempt to request the floor while another User is talking, you’ll see a “Floor Denied” message in
the notification area, as well as hear an audio notification that you failed to acquire the floor. If this
happens, simply wait for the User who’s talking to finish, then request the floor again.
When you wish to leave the network, simply close the application.