YouCast: Tree-based Peer-to-Peer Video Streaming Service

Natalia Chernenko Stanley (Xinlei) Wang Matt Zitzmann Recitation: Girod 1PM May 10, 2007

Natalia Chernenko Stanley (Xinlei) Wang Matt Zitzmann

YouCast: Tree-based Peer-to-Peer Video Streaming Service 1. Introduction The YouCast system is a scalable and reliable peer-to-peer streaming solution that allows multiple users to watch video streams in real-time. In the system, a video server obtains video content from a camera, and streams the content to subscribers in the peer-to-peer network. Since there can be many video servers, a tracking server maintains a list of IP addresses of all active video servers. In this paper, we describe a tree-based video dissemination architecture with the video server as the root. Peers in the tree are both clients as well as servers for peers in the next level of the tree. The tree has an average branching factor of 3. Thus, more than 170,000 peers can be accommodated with a tree of only 10 peer levels. Our system operates according to a set of protocols that govern how new nodes join the system, how video is disseminated, how node failures are repaired, and how private streams are encrypted. All video data is streamed over UDP. All other communication between machines on the system is over TCP/IP. Our design is based on the key principles of keeping the design simple, minimizing the network traffic, and ensuring that our system is scalable. We choose a relatively simple tree structure over more other more complex structures. We minimize network traffic by eliminating unnecessary pinging and messaging between machines on the network. We ensure that our system is scalable by choosing a dissemination structure and private stream encryption method that allow our system to easily accommodate thousands of peers.

2. Tree-based Dissemination Architecture The structure of our dissemination network is represented by a tree with a branching factor of three for most of the nodes. As shown in Figure 1, each node in the tree corresponds to a peer in the network. Each peer can handle on average five concurrent streams. One of these streams is used for receiving video content from the peer’s parent. Three outgoing streams are used for streaming video to the peer’s children. The fifth stream is normally left unused so that repair operations can be accomplished swiftly.


Natalia Chernenko Stanley (Xinlei) Wang Matt Zitzmann

Tracking Server Video Server




Video Server










Figure 1. Tree architecture of the YouCast system. Arrows correspond to dependencies between the nodes of the network. Each peer has a primary parent (solid arrow), and a backup parent (dashed line), which are assigned when it joins the network.

Each peer in the tree has a primary parent as well as a backup parent. A peer only streams video from its primary parent. The peer retains the IP address of a backup parent in case its primary parent fails. When new peers join the network, the video server attempts to assign backup parents to each new peer such that different backup parents are assigned to peers streaming from the same primary parent. The video server also attempts to assign backup parents to new peers such that the backup parent is on the same level of the tree as the primary parent of the new peer. The video server stores the state of the tree in its memory. This is feasible because if each node needs 1 KB of memory, then a tree with 1 million nodes will use 1 GB of memory – a reasonable amount by today’s standards. Table 1 lists the specific information that the video server stores about each peer in the network. The video server gathers all information in this table when the peer joins the network.
Table 1. Data stored about each peer at the video server. This information is stored in each node of the tree data structure in the video server’s memory. Information IP Address Bandwidth Connection Type Primary Parent IP Description Node’s IP address Node’s connection bandwidth in Mb/s How this node is connected to the Internet (wired or wireless) IP address of this node’s primary parent


Natalia Chernenko Stanley (Xinlei) Wang Matt Zitzmann
Backup Parent IP Children IP Addresses Backup Children IP Addresses Join Score IP address of this node’s backup parent List of IP addresses of children of this node List of IP addresses of nodes that use this node as backup parent Used to determine best parents for new peers (see Section 3)

IP addresses serve as the identification of each peer on the network. For basic functionality, either the parent or the children IP addresses needs to be saved for each node. However, to make the video server efficient, we choose to store both the parent and children IP addresses for each node. The connection type data is used to evaluate the reliability of the peer. Wired connections are considered much more reliable than wireless connections because wireless connections have a higher packet drop rate. Using the bandwidth and reliability data of each peer, the video server periodically reshuffles adjacent peers (i.e. parent-children relationship) in the tree to maximize the chance that the peers with the highest bandwidth and strongest reliability are positioned near the top of the tree. The state of the tree stored at the video server is not necessarily the exact current state, but is adequate for our protocols to function correctly. The video server updates the tree when a new peer joins or when a peer tells the video server that the peer’s parent has failed. The video server also updates the tree when a leaf drops out, in which case the parent of the leaf sends a message to the video server. The parent of the leaf knows about the leaf’s state because when a leaf is functional, it sends frame-resend requests (when frames get lost in the network) or keep-alive messages to its parent such that at least one message is sent every three seconds. An alternative design choice is to have the video server ping every peer periodically so that it can maintain the latest version of the tree. We chose to avoid this solution because it requires too much network traffic, which would decrease the efficiency of our system.

3. Join Protocol When a new peer joins the network, the new peer first asks the tracking server for the IP address of the video server. The new peer then uses this information to ask the video server for the IP addresses of a primary parent and a backup parent. The video server responds by giving the new peer the IP address of the available parent with the highest join score (see next paragraph), along with a feasible backup parent.


Natalia Chernenko Stanley (Xinlei) Wang Matt Zitzmann If the primary parent is unavailable, the new peer will ask the video server for another set of primary and backup parents. During join, the video server also does its best to ensure that children of the same peer are given different backup parents on the same level of the tree. The join score is a score calculated for each peer in the client tree when the peer joins. This score takes into account the bandwidth and the reliability of the node. Each peer can find out about its bandwidth and connection type (wired vs. wireless) by asking its network card. The peer then sends this information to the video server. If the peer has a wireless connection, the peer’s join score is calculated by the formula: 2/3*bandwidth. If the peer has a wired connection, then its bandwidth is the join score. The formula is based on the common estimate that a wireless connection can drop 33% of the packets when its bandwidth is fully utilized [1]. The video server maintains a priority queue of leaf nodes with the join score as the key. This way, IP addresses of the best leaf nodes can be given out with little processing time when a new peer requests it.

There are rare cases where the video server may ask a new peer to connect to a failed peer because the video server does not yet know that the peer failed. One case is that a leaf fails, and then its parent fails before the parent can notify the video server. Another case is when a new peer is asked to connect to a leaf that has just dropped out, before the leaf’s parent can notify the video server. In both cases, the new peer can still join correctly by asking the video server for alternative parents. These cases are also likely to be rare, so a new peer usually receives a valid parent IP address on the first try.

4. Dissemination Protocol The dissemination protocol governs how video data is dispersed among clients and servers. In our model, the video server functions only as the main server and the machines that connect to it function as both clients and servers. 4.1 Dataflow The flow of data begins at the video server, which sends packets to the clients connected directly to it. Each packet contains a frame of video and a sequence number of that frame. The server has a buffer that contains 1 minute of video data. This buffer is needed because if one of the clients is missing a frame, it can request the server to resend it.


Natalia Chernenko Stanley (Xinlei) Wang Matt Zitzmann Each peer receives the frame data and places it into its buffer. These frames may be out of order and some may be missing. The peer sends the unordered frame data to all of its clients immediately as it is received to minimize network latency. It then rearranges the frames and requests its parent to retransmit ones that have not yet been received. If it has not received some frames by the time it should play them, the peer ignores the gap and plays the preceding frame instead. The peer’s children can request missing frames from the peer’s buffer. If a peer has not requested a frame for 3 seconds, it sends a keep-alive message to its parent. It is through these keep-alive messages and frame requests that a parent knows that its child should be given content. A child cannot distinguish whether its parent is a peer or the main video server. The YouCast system is optimized for smooth streaming in a tree that is up to 11 levels deep (10 levels of peers). This tree will contain 177,146 peers, assuming that each peer can support an average of 5 streams. One stream will be the incoming data, three will be outgoing data to children, and one will be kept open, so that the peer can serve as a backup parent in case of failure in other nodes. The system will function with deeper trees, but peers at the lower levels of the tree may miss several frames of data in the case of a failure or when the nodes in the tree are reordered. The frame data is sent using the UDP protocol, which does not guarantee delivery. We take this approach in order to send the frame data in a timely manner. The other messages, such as requests for missing frames, are sent using TCP/IP, which is much more reliable. 4.2 Reshuffling In order to optimize the network and prevent situations where less reliable peers are closer (in terms of hops in the tree) to the main server, we utilize a reshuffling algorithm. After a peer has joined the network, and has its buffer nearly full, the main server reshuffles the system to optimize it, placing the closest, most reliable peers at the top of its tree structure. It does this reshuffling two levels at a time, switching in a parent-child pairwise fashion. For example, a parent and a child may switch, but nodes within the same level cannot. Also, nodes may not skip levels. For example, a node in the seventh level can switch with a node in the sixth level, but not with a node in the second level. It can move this high in the tree, however, if it does so progressively, moving up one level at a time. This technique allows the buffers of nodes to fill as much as possible before moving. After moving the server updates the backup parents of the switched peers. This strategy helps minimize latency.


Natalia Chernenko Stanley (Xinlei) Wang Matt Zitzmann 4.3 Buffering The YouCast system streams video data from servers to clients. The clients, in turn, function as servers to their children. When the data travels across a network, the packets with video frames may arrive out of order or be lost entirely. This method requires that the peers in the network, as well as the main video server, have buffers in which they can store video frames. As servers, they may need to retransmit frames to their children. As clients, they need to place the frame packets in the correct order before displaying them on the screen. The challenge of designing a buffering scheme for a real-time peering network lies in network latency. Frames require a certain amount of time to travel between nodes. If it takes one second to travel between two given nodes, then, in a tree with 11 levels, the maximum difference in time from the main video server to the lowest level of the tree will be 10 seconds. If a server sends a frame at time t seconds, a leaf at the lowest level will receive it at t + 10 seconds. In addition, if a peer’s parent fails and its backup is not available, it will need a maximum of 9 seconds to reestablish a connection with a new parent (1 second to realize that it is no longer receiving content, 2 seconds to send a message to its parent and determine that there is no response, 2 seconds to contact a backup parent and establish that it is unavailable, 2 seconds to contact the main video server and obtain a new parent, and 2 seconds to connect to the new parent). The repair section of this document contains a more detailed explanation of how a peer deals with parent failure. Because the maximum latency from the main server to a peer plus the time for repair is 20 seconds and peers can move within the tree, a given peer needs to have 20 seconds of buffer space in which to store frames before playing them. As described earlier, peers in the YouCast system may periodically move up or down in the tree to optimize network function. Peers with higher bandwidth, for example, are better to have at the top of the tree (closer to the main video server), rather than close to the bottom. Because the position of the nodes is not static, the peers’ buffers need to account for network latency, as well as being able to handle being clients and servers either higher or lower in the tree structure without interrupting the video stream or playback. Taking into account that the maximum smoothly supported depth of the tree is 11 levels, our system provides each peer with a 60-second buffer. This buffer is divided into three parts: the section into which frames arrive and are sorted before being played (20 seconds), the section into which data is stored after having been played (20 seconds), and extra buffer space for frames that are sequentially newer than the


Natalia Chernenko Stanley (Xinlei) Wang Matt Zitzmann 20-second sorted frames to be played (20 seconds). The played buffer is used to allow for smooth video playback in case of parent failure. The buffer section with the old data is used so that if a node that was originally at the top of the tree moves to a place near the bottom, it can support its children’s requests for missing frames. The buffer section with the new data is used in case a peer moves from the bottom of the tree to the top. It will have gained extra frame data in the process of its progressive move upward. It will need this space so that its buffer does not overrun. It also needs to store this data to be able to support its children’s requests for missing frames. Please see Figure 3 for an illustration of how these buffers are allocated and Figure 4 to see the how the video content changes for nodes that move up or down in the tree structure.
Sequence # New Frame

Peer’s Video Buffer (30 MB)
Post-Play Section (20 Sec) Oldest Frames Pre-Play Section (20 Sec) Flexible Section (20 sec) Newest Frames

Play Frame Figure 3. Three sections of each peer’s video buffer.

Buffer Content of Peer Bubbling Down 10 Consecutive Times
Joins at 1 Level At 6th Level At 10th Level +20 sec 0 sec -20 sec -40 sec

Buffer Content of Peer Bubbling Up 10 Consecutive Times
Joins at 10 Level At 6th Level At 1st Level +20 sec 0 sec Buffer Space Occupied by Content Unused Buffer Space -20 sec -40 sec

Figure 4. Occupied and unused buffer space for peers moving up or down the tree for 10 consecutive times. The 0second mark corresponds to the current frame being played.


Natalia Chernenko Stanley (Xinlei) Wang Matt Zitzmann The peers begin playing the video after they have received approximately 20 seconds of data. If a client has not received a needed frame within 100 milliseconds (2 frames) of the time it must be played, it simply displays the previous frame. It does, however, request this frame from its parent, so that it can transmit it to its children. Parents obtain the frame data that they transmit to their children from any of the three sections of the buffer.

0th Level 1st Level 2nd Level
Node B

Video Server

. . .


. . .
Max Latency 10 sec

. . .

. . .

9th Level 10th Level


Node A

Figure 5. Illustration of positions of Node A and Node B. Each link between consecutive levels of the tree contributes to a max latency of 1 second. Arrows point from child to primary parent.

To illustrate how the buffering works, consider a node (Node A) at the tenth level of a tree (considering the server to be the 0th level) with a total network latency of 10 seconds (Figure 5). It receives data 9 seconds after a node (Node B) at the first level of the tree receives it, and 10 seconds after the video server disseminates it. Node A buffers the frames for 20 seconds and begins to play the video. Since Node B also buffered its data for 20 seconds before playing it, Node A is now playing its video 9 seconds after Node B. In this case, Node A plays a given frame 30 seconds after the main video server has disseminated it. Suppose now that because Node A is a very high-bandwidth node with a wired connection, it gets promoted to the top of the tree structure. It is still playing frames 30 seconds behind the server, but its


Natalia Chernenko Stanley (Xinlei) Wang Matt Zitzmann children are playing their video only 22 seconds behind the server. The other 8 seconds of data need extra buffer space to prevent buffer overrun. Also, even though Node A transmits frames as soon as it receives them, it needs to be able to answer its children’s requests for missing frames. In case one of Node A’s parents breaks before Node A reaches the top of the structure, it needs to be able to recover within 10 seconds. To allow for both repair and movement up the tree, the flexible buffer space is designed to hold up to 20 seconds of frames. Now suppose that Node B is a low-bandwidth node and gets demoted to the ninth level of the tree (one above the lowest level). It is playing its video 21 seconds behind the server, while its children are playing it 30 seconds behind. In case they request frames, Node B needs to provide them with data that it has already played. In this case, it needs to store old data. We allocate 20 seconds to this buffer to allow for the 10-second difference and repair. Because the nodes keep data from the past and potentially, to them, more than the standard buffering time of 20 seconds into the future, the nodes are free to move within the tree. The server maintains 60 seconds of frames to support all children’s frame requests, regardless of where they originally joined the tree. This scheme allows the tree to be dynamically optimized. 4.4 Pseudocode Functions for handling frames run on each server in the network. There are two versions of these modules, one runs on the main video server, while the other runs on each of the peers. On the video server, the camera that is generating the visual output calls the function Frame_Handler(frame_ptr pt) every 50 milliseconds. The frame handler places the frame into its buffer and sends it to all of the server’s direct children. It places the frame into the buffer first, so that if one of its children requests a frame before the server is finished sending it to all the children, it can fulfill the request. When a child is missing a frame, it can send a message back to the server, asking for a particular frame. The module that handles retransmission of frames runs as a separate thread on the server. When called, it finds a needed frame and sends it to the child that requested it. The following pseudocode is a representation of these modules. These are modules that run on the main video server.


Natalia Chernenko Stanley (Xinlei) Wang Matt Zitzmann
Frame_Handler(frame_ptr pt) { Place_frame_in_buffer(pt, frame_buffer); for_each(child, children) { Send_Frame(ptr, get_ip(child)); } } Retransmit_Missing_Frame(sequence_number frame_num, IP_address child) { frame_ptr pt = Find_frame_in_buffer(frame_num, frame_buffer); Send_Frame(pt, child); }

Each peer runs four threads: one for receiving frames, placing them in the appropriate buffers, and disseminating them, one for sorting and otherwise managing the buffers, one for playing frames, and one for retransmitting missing ones to the children. The pseudocode is shown in below.
Receive_Frame(frame_ptr pt, IP_address source) { Place_frame_in_preplay_buffer(pt); for_each(child, children) { Send_Frame(ptr, get_ip(child)); } } Manage_Buffers() { Sort_preplay_buffer(); // Sorts all but 2 frame slots // closest to play time if(missing_frame) { frame_ptr ptr = request_missing_frame_from_parent( Get_Frame_Seqn(frame)); place_frame_into_buffer(ptr); } if(not_requested_frame_for_3_seconds) { send_keep_alive_to_parent(); } } Play_Control() { every(50 milliseconds) { frame_ptr pt = get_current_frame(); Play_Frame(pt); move_frames_in_buffer(); // Moves played frames to // post play section of // buffer, moves new // frames closer to play time } } Retransmit_Missing_Frame(sequence_number frame_num, IP_address child) { frame_ptr pt = Find_frame_in_buffer(frame_num, frame_buffer); if(frame_in_buffer) { Send_Frame(pt, child); }


Natalia Chernenko Stanley (Xinlei) Wang Matt Zitzmann

This code runs on the peers and manages the flow of the data in the network. It is optimized for fast dissemination. 4.5 Backups Each client in the network has one parent and one backup parent to which it can connect in case its primary parent fails. The number of children each parent has is one less than the maximum number of streams it can support, so that it is capable of fulfilling its backup parent responsibilities. We keep only one stream open because we assume that only one node in the network may fail at any one time. Also, the server, to the best of its ability, assigns backup parents to nodes in such a way that children of one primary parent do not share backup parents. It attempts to assign backup parents that are on the same level as the primary parents. Because these children do not have the same backup parent, if their primary parent fails, the backup parents, each of which keeps one stream open for such emergencies, can support these nodes. It is possible that a backup parent is unavailable at the time its child requests a stream. In this case, the child asks the server to rejoin the tree.

5. Repair Protocol If during a one second interval, a peer receives little (less than 20%) or no content, it contacts its parent to check if it has failed. If the parent responds, then the peer will continue to receive content from the parent as usual. If there is no response, then the peer deems that its parent has failed. Upon determining that its parent has failed, a peer will first request the stream from its backup parent. If the backup parent is able to handle an additional outgoing stream, it begins streaming to the peer. Once the peer begins receiving content from the backup parent, it sends a message to the video server to update its tree structure. The server responds to the peer with a new backup parent in case of another failure. Since peers can disconnect from a stream at any time, it is possible that a peer’s backup parent is no longer a part of the system. In this case, the peer uses the join protocol to request new primary and backup parents.


Natalia Chernenko Stanley (Xinlei) Wang Matt Zitzmann Although all parents maintain one open outgoing stream each to fulfill their backup parent responsibilities, it is feasible that this slot is filled by a different peer from either another failure or the same failure. A backup parent can be a part of the system, but simply unable to handle an additional outgoing stream. Similarly to the above case, the peer uses the join protocol to request new primary and backup parents. In the case where a parent has no available outgoing streams, we do not reshuffle any of its children to reopen a slot. Thus, this parent can no longer fulfill its backup parent responsibilities. The video server instead will send a message to every peer that has a backup parent with no open slots, updating these peers with new backup parents. This allows these peers to receive content more quickly after a failure because they no longer have to contact a full backup parent. Our failure design does not introduce large overhead. In most situations, there is only one roundtrip of communication before a peer begins receiving content from its backup parent. If a backup parent is unavailable or unable to handle an additional outgoing stream, there are three roundtrips of communication before a peer begins receiving content again. By minimizing this overhead, our system is able to maintain scalability.

6. Private Streams Our system uses shared-secret cryptography for private streams. Using e-mail correspondence, the camera owner sends each user the same shared-secret key. Thus, only one secret key is distributed to every peer in the system. The server will encrypt each frame before it is sent to its children. Note that the server only encrypts the video content of the frame, and not the entire packet which includes the sequence number, because we are interested in securing only the video content. No significant changes are necessary to the system, except that a peer must now decrypt any content received for a private stream using the sharedsecret key that the camera owner sent. Also, peers will only decrypt the content immediately before it is played so that it can respond to a child’s request for a specific (encrypted) frame very quickly. Since the video content is encrypted as it is sent across the network, peers without the shared-secret key are unable to watch the stream. Nonetheless, these peers are still able to stream the content to their children. All peers transmit encrypted video content so that only peers with the shared-secret key are able to view the stream.


Natalia Chernenko Stanley (Xinlei) Wang Matt Zitzmann

Although using public-key cryptography is theoretically possible for this situation, it is far less efficient than shared-secret cryptography. Public-key cryptography is computationally more costly. In fact, it can be hundreds or even thousands of times slower than shared-secret cryptography [2]. Public-key cryptography with multiple public keys is not a scalable solution because every peer would need to receive a unique encrypted frame. For each peer, the server would have to encrypt the frame with the peer’s public key. If there are n peers, then for every frame of video content, n unique frames will need to be sent out. Since all the peers share the same key in shared-secret cryptography, it is only necessary for the video server to send out a single encrypted frame.

7. Scalability and Fault Tolerance 7.1.1 Scalability – Join By using a simple tree structure, our system is able to maintain scalability. On average, a machine can handle 5 streams. In our system, there is only one incoming stream for a given peer, leaving four outgoing streams. In general, all parents leave one of their four streams open to fulfill their backup parent responsibilities. To simplify our analysis, we will assume that our tree has a consistent breadth of three for each peer and that it is balanced. Even if there are over 170,000 peers connected to a single stream, the tree only has ten peer levels. Thus, the amount of time it takes for a frame to travel from the top of the tree to the bottom is a maximum of 10 seconds. For each additional level of the tree, the system grows exponentially. For example, with 13 peer levels our system can accommodate over 4.7 million peers with a maximum delay of 13 seconds from the top to the bottom. One weakness of our design with respect to scalability is that it can be somewhat slow when numerous peers all join at the same time. This occurs because the video server needs to determine where each peer in a certain level resides. Then, it focuses on the next level of peers and so on. The system slows down in this situation, but we chose to avoid implementing a workaround to maintain a simple design. 7.1.2 Scalability – Dissemination


Natalia Chernenko Stanley (Xinlei) Wang Matt Zitzmann Our system scales well because the video server does not have to support every client. The system minimizes latency by having the peers transmit received packets as quickly as possible (without buffering them first) and by reshuffling peers, putting the most capable ones at the top of the hierarchy. The capabilities of the system are not infinite, however. Although we describe our system as being optimized for a tree of maximum depth 11, it can be extended to account for a greater number of nodes by increasing the size of the buffers on the video server and peers. The administrator of the system would adjust the size of the buffers before beginning to transmit the stream to the peers. The number of clients would be estimated before running a given stream on a video server. 7.2 Fault Tolerance As a peer attempts to reconnect to its backup parent or to a new parent, it consumes video content from its buffer. In most cases, it takes the peer a maximum of 9 seconds to begin receiving content again. In general, it takes the peer a maximum of 3 seconds to determine its parent has failed and, in the case of the backup parent being unavailable, a maximum of 6 seconds to begin receiving content from a new parent (assuming a maximum network latency of 1 second). Thus, a buffer size of 20 seconds is large enough to ensure that a peer maintains a quality stream for the viewer. One specific situation where a peer may have a loss of performance in the video stream is when its parent fails, backup parent is unavailable, and rejoining the system takes a significant amount of time. In this case it takes the peer longer than 6 seconds to begin receiving content from a new parent. We estimate this situation to be rare and because the buffer maintains roughly 20 seconds of content, we do not foresee this problem having a significant impact on the system. 8. Conclusion

We have designed a scalable, robust, and high-performance video streaming system that operates according to the join, dissemination, repair and private stream protocols. The tree-structure and the absence of unnecessary communication make our system scalable. Our repair algorithm allows for a peer to quickly find a new parent while using its buffer to maintain the stream of video content. Our dynamic node reshuffling algorithm makes our system perform well by moving the most reliable nodes to the top of the tree.


Natalia Chernenko Stanley (Xinlei) Wang Matt Zitzmann

Before our design can be implemented, some specific parameters should be tested empirically. These parameters include the 3-second keep-alive message interval, as well as the 20% content threshold for running the repair protocol. The low level details of the algorithm for assigning backup parents according to our criteria also need to be determined. Efficient methods of storing the tree structure in memory of the video server should be explored. Geographical location of peers could be considered in more advanced versions of this system. Finally, video network traffic flow properties should be studied to optimize the system.

9. Acknowledgements We acknowledge our recitation instructor, Lewis Girod, and our teaching assistant, David Schultz for providing us with valuable feedback on our design.

10. References [1] M. G. Arranz, R. Aguero, L. Munoz, and P. Mahonen, “Behavior of UDP-based applications over IEEE 802.11 wireless networks,” IEEE International Symposium on Personal, Indoor and Mobile Radio Communications, vol. 2, no. 2, Sep.-Oct., pp: F-72-F-77, 2001. [2] D.A. Menasce, “Security performance,” IEEE Internet Computing, vol.7, no. 3, May-Jun. pp: 84-87, 2003.

Word Count: 5360