• Aucun résultat trouvé

T echnical D esign A nd I mplementation

4.2 The Architecture - The Herd Framework

4.2.3 Core Plugin Library

4.2.3.2 User Datagram Protocol node

The benefit of using UDP is speed, which is favourable for services where guaranteed transfer of data is of lower importance. Since UDPis connectionless it does not serve well for session based services, however with a small extension and without reimplementing the whole TCP stack of functionalities it is preferable using it for input events and video streaming. For video streaming then sender side compresses a frame and sends it to the other side, which decompresses the frame again, this however entails that the codec used should be able to handle lost frames. As for input events similar rules are applied, for example mouse movement is a stream of screen coordinates of the mouse pointer, losing a couple of these events is not critical. However

when-ever there is amouse button pressit is a more important event. We therefore introduce two types of UDP based streaming, command and stream, as can be seen in the class diagram figure 4.14.

These implementation are solely used for the framework presented and alike to theHerdTcpNode serve its purpose for the presented use-cases. Other protocols based on UDP such as RUDP, DHCP, RTP etc. should be encapsulated into their own respectiveHerdNode.

HerdNode

Both types extend on theHerdUdpInterfacewhich is similar to theHerdTcpCore, handling connec-tions, sending and receiving data. Since there are no sessions it is left to the implementation of the service/application on how to handle this if needed. This might be done by using per application session a different socket, or provide additional information in the data packet. The actAsServer starts listening to a given socket and handles any data that it receives on it, it does not know anything about sending data at this point. Where the actAsClientis given an address to where it has to send(connect), it does not check if it exists as it will firepackets into the net unknowingly if it ever arrives. Whenever the server receives datagram packets it will use the senders address as its new reply address. In practice this works fairly well, and in fact most networked games work use UDP for player movements. TheHerdUdpInterfacekeeps a buffer for the received datagrams, usingHerdUdpSequenceobjects. A datagram is limited in size (theoreti-cal limit of 655074, but commonly a size of around 1400 bytes or less is used) and therefore the transfer of data can be split into several datagrams. Furthermore the datagrams can arrive in an unordered fashion, meaning that for example sending twoHerdDataPacketobjects can be split

465535 minus the Internet protocol (IP) header and UDP header itself

Table 4.3:UDP buffer cell structure

Cell Header Packet header Body

Parent packet offset type sequence info field data

4 bytes 1 byte 1 byte 2 bytes max (udp packet size - header size)

into several datagrams and be received in a mixed order. Depending on the network hardware and lower level implementation, the buffer for receiving packets is limited, which can lead to flooding of the buffer when receiving too many packets. To avoid this the buffer must be read constantly and must not loose time on later processing of the data and from practice this turned out to be quite tricky. To handle UDP quickly and correctly (incorporating the possibility of fragmentation) we encapsulate the HerdDataPacketinto a new packet and use a fixed buffer for placing the incoming data without any further processing. The method we came up with proofed to be quite fast and foremost easy to use. The fixed buffer is a one time memory pool allocation, which can contain an X amount of datagrams. Each datagram has an additional header of 4 bytes and the data within the datagram also contains a 4 byte header for the data, this is shown in table 4.3. The fields within a cell are:

• Parent packet offset, during writing a cell an offset to its parent cell with the same sequence is written here and the new latest offset is kept in the sequence object.

• Type, indicates the packet state. Possible values are

Value 1 Indicating the first packet of a sequence of packets.

Value 2 An in between follow-up packet or so called sequence packet.

Value 4 The final packet for a sequence of packets.

Value 8 A singular packet that is the first and final packet (simply a single packet).

• Sequence, UDP streaming can keep track of maximum 256 different packet sequences the sequence ID is the index number

• Info, The packet number (maximum packet numbers 65535)

Assume the maximum size for a datagrams is set to 1450 bytes and the buffer is set to 1 MiB, for each datagram stored 4 bytes of additional data is used, therefore 721 datagrams can be stored into it, which we call cells. Even if a datagram is not using its full capacity, it will be registered as a full cell in the buffer. Upon receiving a datagram, a single memory copy is used to place it into the buffer at the current buffer offset, which thereafter increments. The offset resets to the beginning of the buffer at the last cell, creating a ring buffer. A secondary buffer is used for managing and registering the incoming packets, which is an array of 256 HerdUdpSequence objects. For each sequence number (0-255) there is an HerdUdpSequencethat keeps track of any incoming datagrams with the given identifier. This procedure is illustrated in figure 4.15.

Note that data received is directly written into the buffer and a pointer is used for indicating the start of the cell in the buffer. At the end there is a check if the active sequence is complete,

Set active buffer cell Put sequence id into micro

buffer If true

Figure 4.15:Reading UDP packets.

meaning it either has a single packet of type 8 or the internal count of packets is equal to the expected count of packet (which is the packet number from packet type 4). The identifier of the sequence is placed into a micro buffer, which in case of streaming has a limited amount (e.g. 4 identifiers). It also sorts the identifiers with a relaxing sort at the end of the buffer as we want sequences with a lower identifier handled first, but at the end it can occur that sequence 255 comes a bit late and sequence 0 has been placed already, then we still want 255 to be handled first, but still after 254. The placements of the identifiers into the micro buffer is thread-safe and from another thread the available identifiers are retrieved. This reduces the amount of operations to be done within the actual networking thread and minimized the chance of packet flooding.

Packets are still being dropped if the micro-buffer is full, but it will push out the older ones first.

Whenever an identifier is retrieved in the other thread, the sequence object is accessed and a the functiongetSequenceis called. A newHerdDataPacketobject is created and the needed amount of memory is allocated.

Figure 4.16:Retrieving a data packet from the buffer.

Shown in figure 4.16 is the buffer with several cells illustrated. The first cell has 0 for offset, 8 for type meaning it is a single packet in this cell, sequence id 30, info set to 1 as it is packet number 1 and the data is markedXas this can be the maximum size of the remaining cell space. In this case we want to retrieve sequence 31 which is composed out of several cells and spread out with higher sequence numbers in between and incorrect order. The latest received data contained

packet number 3, therefore the HerdUdpSequenceobject is pointing to offset 6 internally, it will take the data and place it directly into theHerdDataPacketat position 3, then it will read the offset from the cell header, which is pointing to 4, thus the next cell at offset 4 is read and placed. This procedure is continued until the HerdDataPacketis filled. Afterwards theHerdDataPacketobject is forwarded to thehandlePacketfunction where it is either buffered or redirected to the callback function.