Example #1
0
        /// <summary>
        /// Sends byte[] to socket.
        /// Creates datagram with frame format given as example in demonstration example.
        /// Switches state to waitingforack.
        /// Set sendAsIs when sending/resending valid datagram/frame.
        /// </summary>
        /// <param name="data">Byte array to be sent over socket</param>
        /// <param name="sendAsIs">Boolen: true - datagram has been contructed before, false - construct new datagram and send it</param>
        protected virtual async void RdtSend(byte[] data, bool sendAsIs = false)
        {
            if (sendAsIs)
            {
                socket.Send(data);
            }
            else
            {
                switch (state)
                {
                case (int)STATE.WaitingCallFromAboveOrBelow:
                {
                    byte[] newDatagram = rdt.MakeDatagram(data, senderSeq);
                    socket.Send(newDatagram);
                    previouslySentDatagram = newDatagram;
                    state = (int)STATE.WaitingForAck;
                    break;
                }

                case (int)STATE.WaitingForAck:
                {
                    RaiseOnDeliver(InvokeReason.Error, "Waiting for ACK/NACK, add to queue.");
                    messageBuffer.Add(data);
                    break;
                }
                }
            }
        }
Example #2
0
        private async void RdtSend(byte[] data, bool isOldDatagram = false)
        {
            if (isOldDatagram)
            {
                /*data has been sent before so it has seq nums etc*/
                socket.Send(data);
            }
            else
            {
                /*data is just new content as byte[] so new datagram is needed*/
                /*nextseqnum<base+N will fail when seqnum range overflows*/
                if (rdt.Distmod(gbnBase, gbnNextSeqNum, gbnWindowSize) < gbnWindowSize - 1)
                {
                    try
                    {
                        OnDeliver?.Invoke(InvokeReason.Debug, "4a" + PrintGbnDebug());

                        byte[] newDatagram = rdt.MakeDatagram(data, gbnNextSeqNum);
                        gbnSendDictionary[gbnNextSeqNum] = newDatagram;

                        socket.Send(gbnSendDictionary[gbnNextSeqNum]);
                        //simplify with pre-increment and combine following operations
                        gbnNextSeqNum = gbnNextSeqNum + 1;
                        gbnNextSeqNum = gbnNextSeqNum % gbnWindowSize;

                        OnDeliver?.Invoke(InvokeReason.Debug, "4b" + PrintGbnDebug());

                        if (cts != null)
                        {
                            cts.Cancel();
                        }
                        /*All standing packets are ack'd*/
                        if (gbnBase == gbnNextSeqNum)
                        {
                            //OnDeliver?.Invoke(InvokeReason.Debug, "Sending window is empty.");
                        }
                        else
                        {
                            //start new timer
                            //TODO: Check if this leaks resources
                            CancellationTokenSource aCTS = new CancellationTokenSource();
                            cts = aCTS;
                            await Timertimeout(aCTS.Token);

                            /*
                             * if (cts == aCTS)
                             * {
                             *  cts = null;
                             * }
                             */
                        }
                    }
                    catch (OperationCanceledException) { }
                }
                else //send window is full
                {
                    OnDeliver?.Invoke(InvokeReason.Error, "Sending window is full, try again later.");
                }
            }
        }
Example #3
0
        private async void RdtSend(byte[] data, bool isOldDatagram = false)
        {
            if (isOldDatagram)
            {
                socket.Send(data);
            }
            else
            {
                byte[] datagram = rdt.MakeDatagram(data, srNextSeqNum);
                sendBucket.AddToBucket(datagram, srNextSeqNum);
                if (rdt.IsSeqInRange(srNextSeqNum, srSendBase, (byte)(srSendBase + srWindowSize - 1)))
                {
                    //Send via socket
                    socket.Send(datagram);
                    sendBucket.MarkAsSent(srNextSeqNum);
                    //start timer for this packet or set timestamp to simulate via single timer

                    sendBucket.SetTimestamp(srNextSeqNum);


                    OnDeliver?.Invoke(InvokeReason.Debug, "Message sent" + PrintSRDebugInfo());
                }
                else
                {
                    OnDeliver?.Invoke(InvokeReason.Debug, "Message Buffered" + PrintSRDebugInfo());
                }
                srNextSeqNum++; //pre-increment is more efficient here? edit: compiler optimization -> no difference
            }
        }