Exemple #1
0
        /// <summary>
        /// Callback for asynchronous send, if data is left to send, then send the remaining data, otherwise go into wait for acknowledgement state.
        /// </summary>
        /// <param name="ar">An IAsyncResult that references the asynchronous send.</param>
        private void SendCallback(IAsyncResult ar)
        {
            ClientState state    = (ClientState)ar.AsyncState;
            int         sentData = state.Socket.EndSend(ar, out SocketError socketError);

            Diagnostics.LogInfo(Helper.ContextLogger(string.Format("BytesSent : {0}   TotalBytes: {1}", sentData, state.DataToSend().Length), 2));

            if (socketError != SocketError.Success)
            {
                Diagnostics.LogError(Helper.ContextLogger("SocketError EndPoint :: " + Helper.GetEndPoint(state.Socket), 0)); // Socket Failed
                this.ResetClient(Helper.GetEndPointAddress(state.Socket), state.IPPort);                                      // Remove any lock-objects,sockets,status bit associated to failed socket.
                lock (this.ackLock)
                {
                    this.acknowledgeStatus.Remove(Helper.MD5Hash(state.Message) + state.IPPort);
                }

                this.DataStatusNotify(state.Message, StatusCode.Failure);
                if (this.isStudent)
                {
                    this.isRunning = false;
                }

                return;
            }

            state.DataSent += sentData;

            if (state.DataSent != state.DataToSend().Length)
            {   // not all data was sent so send remaining bytes
                state.Socket.BeginSend(
                    state.DataToSend(), state.DataSent, state.DataToSend().Length - state.DataSent, SocketFlags.None, new AsyncCallback(this.SendCallback), state);
            }
            else
            {
                if (state.DataToSend()[4] == 0)
                {
                    Diagnostics.LogSuccess(Helper.ContextLogger(string.Format("EndPoint {0} Message Sent :: {1}", Helper.GetEndPoint(state.Socket), Helper.ShortLog(state.Message)), 1));
                }
                else
                {
                    Diagnostics.LogSuccess(Helper.ContextLogger(string.Format("Acknowledgement EndPoint {0} Message Sent :: {1}", Helper.GetEndPoint(state.Socket), Helper.MD5Hash(state.Message)), 2));
                }

                // Now that all data has been sent we release the lock.
                this.ReleaseLock(state.IPPort);
                if (state.DataToSend()[4] == 0)
                {
                    new Thread(() => this.WaitForAcknowledgement(Helper.GetEndPointAddress(state.Socket), state.IPPort, state.Message, state.Retries + 1))
                    {
                        Name = Thread.CurrentThread.Name + " # Target IP : " + Helper.GetEndPoint(state.Socket)
                    }.Start();
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// Sends a given message by formatting it.
        /// </summary>
        /// <param name="message">The message to be sent</param>
        /// <param name="retries">Tells which retry is this to send the message</param>
        /// <param name="socket">The socket to which send the data on</param>
        /// <param name="isAck">Tells if the message being sent is acknowledgment.</param>
        private void SendHelper(string message, int retries, Socket socket, int isAck)
        {
            // Create a new state object.
            ClientState currentState = new ClientState
            {
                Socket = socket
            };

            if (currentState.IPPort == "0.0.0.0")
            {
                Diagnostics.LogError(Helper.ContextLogger("Called with null socket, not supposed to happen", 1));
                throw new InvalidOperationException();
            }

            byte[] byteData    = Encoding.ASCII.GetBytes(message);
            byte[] lengthBytes = Helper.GetBytes(byteData.Length);
            byte[] ackBits     = new byte[] { (byte)isAck };

            // Every message sent over network has format (prefix = length + ackBit) + message bytes
            // length in prefix excludes the bytes used for length and reservedBits(ackBit)
            byte[] prefix = Helper.Combine(lengthBytes, ackBits);

            currentState.Retries  = retries;
            currentState.DataSent = 0;
            currentState.Message  = message;
            currentState.SetDataToSend(Helper.Combine(prefix, byteData));

            Diagnostics.LogInfo(Helper.ContextLogger("Waiting To Acquire Lock IP EndPoint" + Helper.GetEndPoint(socket), 7));

            // We maintain locks per socket so that more than one thread don't send at the same time on same socket, otherwise data would overlap.
            while (!this.GetLock(currentState.IPPort))
            {
            }

            Diagnostics.LogInfo(Helper.ContextLogger("Lock Acquired. Calling BeginSend EndPoint" + Helper.GetEndPoint(socket), 5));
            lock (this.ackLock)
            {
                this.acknowledgeStatus[Helper.MD5Hash(message) + currentState.IPPort] = new AutoResetEvent(false);
            }

            try
            {
                socket.BeginSend(currentState.DataToSend(), 0, currentState.DataToSend().Length, 0, new AsyncCallback(this.SendCallback), currentState);
            }
            catch
            {
                Diagnostics.LogError(Helper.ContextLogger("SocketError EndPoint :: " + Helper.GetEndPoint(currentState.Socket), 0)); // Socket Failed
                this.ResetClient(Helper.GetEndPointAddress(currentState.Socket), currentState.IPPort);                               // Remove any lock-objects,sockets,status bit associated to failed socket.
                lock (this.ackLock)
                {
                    this.acknowledgeStatus.Remove(Helper.MD5Hash(currentState.Message) + currentState.IPPort);
                }

                this.DataStatusNotify(currentState.Message, StatusCode.Failure);
                if (this.isStudent)
                {
                    this.isRunning = false;
                }
            }

            Diagnostics.LogInfo(Helper.ContextLogger("Returned EndPoint" + Helper.GetEndPoint(socket), 5));
        }