Friday, June 20, 2014

Homemade Internet Service Relay (X)

Ready for receive? Receive is much more complicated than send. Similar to Send, Read happens mostly within Connection. As an overview, Connection spread the work for receive to TransportReceiveActor and ChannelReceiveActor.

TransportReceiveActor deals with the data from transport, demultiplex it, and send to ChannelReceiveActor.
ChannelReceiveActor response to Channel ReadRequest by providing data provided by TransportReceiveActor, after copying back to Channel, ChannelReceiveActor will response to TransportReceiveActor the data is consumed. This is to free buffer to allow space for further receives.

Here is a more detailed view:

TransportReceiveActor maintains a buffer – this buffer is used to store data from TCP transport. Before this buffer is full, TransportReceiveActor keep requesting transport for data. This buffer also serve the purpose of choking the sender. Because of we are at low capacity to process the data, the buffer will remain not empty and receive will not proceed, effectively stopping sender because its TCP sliding window is used up.

After data arrives in the buffer, TransportReceiveActor decodes them. Decoding is a simple state machine – read the channel, read the size, read size bytes, and repeats. However, since data is not available, the state machine must stop when there is no data, and the state is saved until the next packet arrives. Here the unread count is increased by the total size of the payload.

The decoded payloads are then sent to ChannelReceiveActor, one complication arise here if the ChannelReceiveActor is not there yet. This is a new channel! There must be someone else trying to accept the Channel, the payload will be enqueued in pending accept list. If there are any pending accept request, the accept request is satisfied. Beyond that, the data will be sent to the ChannelReceiveActor.


After ChannelReceiveActor received the data, it enqueues it into a queue. The queue is then checked to see if there are any pending read request, and if there is one, try to fill the buffer and return. After filling the buffer, the used count is send back to TransportReceiveActor to reduce the unused count. Once the unused count goes back to 0, transport receive can start again.

No comments :

Post a Comment