/// <summary>
        /// Blocking receive TCP call.
        /// </summary>
        /// <returns></returns>
        public bool ProcessReceive()
        {
            try
            {
                //OwningConnection.MyTCPSocket.Blocking = true;
                SocketDebug(5);
                if (OwningConnection.MyTCPSocket.Connected && OwningConnection.MyTCPSocket.Poll(0, SelectMode.SelectRead))
                {
                    SocketDebug(6);
                    m_TCPBytesReceived = OwningConnection.MyTCPSocket.Receive(m_TCPBuffer, 0, m_TCPBuffer.Length, SocketFlags.None, out m_LastTCPReceiveStatus);
                    SocketDebug(7);
                    Log.LogMsg("Received " + m_TCPBytesReceived.ToString() + " on socket " + OwningConnection.MyTCPSocket.Handle.ToString() + " with socket error reading " + m_LastTCPReceiveStatus.ToString());

                    OnReceiveResolved(false, m_TCPBuffer, m_TCPBytesReceived, m_LastTCPReceiveStatus, m_TCPSockState);
                }
                else if (!OwningConnection.IsAlive)
                {
                    SocketDebug(8);
                    Log.LogMsg("DuplexBlockingTransit can't ProcessReceive because OwningConnection is not connected.");
                    Log.LogMsg("Can't receive on socket " + OwningConnection.MyTCPSocket.Handle.ToString() + " with socket error reading " + m_LastTCPReceiveStatus.ToString());
                    OwningConnection.KillConnection("Couldn't receive. Connection has been closed.");
                    SocketDebug(9);
                }
            }
            catch (Exception e)
            {
                string error = "";// OwningConnection.MyTCPSocket.GetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.Error).ToString();
                Log.LogMsg("Error receiving data on DuplexBlockingTransit. (" + error + ")" + e.Message + ", Stack=\r\n" + e.StackTrace);
                OwningConnection.KillConnection("Connection lost! Network receive error: " + e.Message);
            }
            return(true);
        }
Пример #2
0
        private void SendBytes(bool isUDP, byte[] data)
        {
            try
            {
                if (!OwningConnection.IsConnected)
                {
                    return;
                }

                if (isUDP)
                {
                    SocketDebug(777);
                    OwningConnection.MyUDPSocket.SendTo(data, OwningConnection.UDPSendTarget);
                }
                else
                {
                    SocketDebug(3);
                    OwningConnection.MyTCPSocket.Blocking = true;
                    OwningConnection.MyTCPSocket.Send(data);
                    SocketDebug(4);
                }

                OwningConnection.SentBytes(data);
                OwningConnection.PacketSent();
            }
            catch (Exception e)
            {
                Log.LogMsg("Error SendBytes. " + e.Message);
                OwningConnection.KillConnection("Send error. " + e.Message);
            }
        }
Пример #3
0
        private void IO_Completed(object sender, SocketAsyncEventArgs e)
        {
            try
            {
                // determine which type of operation just completed and call the associated handler
                switch (e.LastOperation)
                {
                case SocketAsyncOperation.Receive:
                    OnReceiveResolved(e);
                    break;

                case SocketAsyncOperation.Send:
#if !SILVERLIGHT
                case SocketAsyncOperation.SendTo:
#endif
                    //Log.LogMsg("Send EVENT completed for @" + ((SockState)e.UserToken).ID.ToString() + "@");
                    OnSendResolved(e, e.UserToken as SockState);
                    break;

                default:
                    //This exception will occur if you code the Completed event of some
                    //operation to come to this method, by mistake.
                    throw new ArgumentException("The last operation completed on the socket was not a receive or send");
                }
            }
            catch (Exception ex)
            {
                Log.LogMsg("Error in IO_Completed. " + ex.Message);
                OwningConnection.KillConnection("Error I/O. " + ex.Message);
            }
        }
        /// <summary>
        /// Gets called when a receive operation resolves.  If we were listening for data and the connection
        /// closed, that also counts as a receive operation resolving.
        /// </summary>
        /// <param name="args"></param>
        private void OnReceiveResolved(bool isUDP, byte[] buffer, int bytesReceived, SocketError status, SockState sockState)
        {
            SocketDebug(19);
            //// Log.LogMsg("==>++++ Async RECEIVE Op Completed - #" + ((SockState)args.UserToken).ID.ToString() + "#");
            try
            {
                if (!OwningConnection.IsAlive && bytesReceived > 0)
                {
                    SocketDebug(20);
                    return;
                }

                SocketDebug(21);
                // If there was a socket error, close the connection. This is NOT a normal
                // situation, if you get an error here.
                if (status != SocketError.Success)
                {
                    SocketDebug(22);
                    Log.LogMsg("Receive status = " + status.ToString());
                    if (!OwningConnection.ShuttingDown)
                    {
                        //// Log.LogMsg("Testy 111");
                        OwningConnection.KillConnection("Connection lost! Network receive error: " + status);
                    }
                    //Jump out of the ProcessReceive method.
                    SocketDebug(23);
                    return;
                }

                SocketDebug(24);
                m_TCPSockState.AsyncEventArgs.RemoteEndPoint = OwningConnection.MyTCPSocket.RemoteEndPoint;

                // If no data was received, close the connection. This is a NORMAL
                // situation that shows when the client has finished sending data.
                if (bytesReceived == 0)
                {
                    SocketDebug(25);
                    if (!OwningConnection.ShuttingDown)
                    {
                        //// Log.LogMsg("Testy 114");
                        OwningConnection.KillConnection("Connection closed by remote host.");
                    }
                    return;
                }

                SocketDebug(26);
                OwningConnection.ReceivedBytes(bytesReceived);

                // restart listening process
                SocketDebug(27);
                OwningConnection.AssembleInboundPacket(buffer, bytesReceived, sockState);
                SocketDebug(28);
            }
            catch (Exception ex)
            {
                Log.LogMsg("Error ProcessReceive. " + ex.Message);
                OwningConnection.KillConnection("Error receive. " + ex.Message);
            }
        }
        protected Queue <NetQItem> m_SendQueue = new Queue <NetQItem>(); // packet send queue

        /// <summary>
        /// Sends arbitrary bytes of data across the wire.  Note that if the remote endpoint can't decipher the data
        /// as a known packet, the connection will be dropped by that endpoint immediately.
        /// </summary>
        /// <param name="data">bytes to send</param>
        public virtual int Send(byte[] data, PacketFlags flags)
        {
            SocketDebug(32);
            //Log.LogMsg("@__@ Monitor Enter");
            if (!OwningConnection.IsAlive)
            {
                Log.LogMsg("DuplexBlockingTransit - cant send data because owning connection isn't alive. MyTcpSocket == Null -> " + (OwningConnection.MyTCPSocket == null));
                Log.LogMsg("Can't send on socket " + OwningConnection.MyTCPSocket.Handle.ToString() + " with socket error reading " + m_LastTCPReceiveStatus.ToString());
                OwningConnection.KillConnection("Couldn't send. Connection has been closed.");
                return(-1);
            }
            SocketDebug(33);
            // Log.LogMsg("==>Sending " + data.Length.ToString() + " bytes.");
            try
            {
                bool isUDP = (flags & PacketFlags.UDP) != 0;
                if (isUDP)
                {
                    SocketDebug(34);
                    if (!OwningConnection.CanSendUDP)
                    {
                        Log.LogMsg("!!! Tried sending UDP packet when the connection wasn't yet ready to send UDP. Dropping packet.");
                        return(0);
                    }

                    SocketDebug(35);
                    // Don't allow fragmenting UDP packets
                    if (data.Length > 1024)
                    {
                        Log.LogMsg("Message exceeded UDP size of 1024 bytes. Sending via TCP instead.");
                        flags &= ~PacketFlags.UDP;
                    }
                }

                SocketDebug(36);
                NetQItem qi = new NetQItem();
                qi.Flags = flags;
                qi.Data  = data;
                qi.IsUDP = isUDP;
                m_SendQueue.Enqueue(qi);
                Log.LogMsg("Send queue now has " + m_SendQueue.Count.ToString() + " items in it.");
                SocketDebug(37);
                return(1);
            }
            catch (Exception sendExc)
            {
                Log.LogMsg("DuplexBlockingTransit - Failed to send data. " + sendExc.Message);
                return(-1);;
            }

            return(1);
        }
Пример #6
0
        /// <summary>
        /// Gets called when a receive operation resolves.  If we were listening for data and the connection
        /// closed, that also counts as a receive operation resolving.
        /// </summary>
        /// <param name="args"></param>
        private void OnReceiveResolved(SocketAsyncEventArgs args)
        {
            // Log.LogMsg("Testy 21");
            // Log.LogMsg("==>++++ Async RECEIVE Op Completed - #" + ((SockState)args.UserToken).ID.ToString() + "#");
            try
            {
                if (!OwningConnection.IsAlive && args.BytesTransferred > 0)
                {
                    // Log.LogMsg("Testy 22");
                    return;
                }

                SockState state = args.UserToken as SockState;
                // If there was a socket error, close the connection. This is NOT a normal
                // situation, if you get an error here.
                if (args.SocketError != SocketError.Success)
                {
                    // Log.LogMsg("Testy 222");
                    OwningConnection.KillConnection("Connection lost! Network receive error: " + args.SocketError);
                    //Jump out of the ProcessReceive method.
                    return;
                }

                // If no data was received, close the connection. This is a NORMAL
                // situation that shows when the client has finished sending data.
                if (args.BytesTransferred == 0)
                {
                    // Log.LogMsg("Testy 223");
                    OwningConnection.KillConnection("Connection closed by remote host.");
                    return;
                }

                //// Log.LogMsg("Testy 224");
                OwningConnection.ReceivedBytes(args.BytesTransferred);
                // restart listening process
                //// Log.LogMsg("Testy 225");
                OwningConnection.AssembleInboundPacket(args, state);
                //// Log.LogMsg("Testy 226");
                ListenForDataOnSocket();
            }
            catch (Exception ex)
            {
                //// Log.LogMsg("Testy 23");
                Log.LogMsg("Error ProcessReceive. " + ex.Message);
                OwningConnection.KillConnection("Error receive. " + ex.Message);
            }
        }
Пример #7
0
        /// <summary>
        /// Serializes and sends a packet across the wire
        /// </summary>
        /// <param name="msg">The packet to send</param>
        public virtual int Send(Packet msg)
        {
            try
            {
                if (msg.NeedsDeliveryAck)
                {
                    m_NumAcksWaitingFor++;
                }

                byte[] raw = OwningConnection.SerializePacket(msg);
                //Log.LogMsg("Sending -> " + msg.GetType().ToString() + " (" + raw.Length.ToString() + " bytes)");
                //Log.LogMsg("   That message is " + raw.Length.ToString() + " bytes long");
                return(Send(raw, msg.Flags));
            }
            catch (Exception sendExc)
            {
                OwningConnection.KillConnection(sendExc.Message);
                return(-1);;
            }
        }
        private void SendBytes(bool isUDP, byte[] data)
        {
            try
            {
                SocketDebug(10);
                if (!OwningConnection.IsConnected)
                {
                    SocketDebug(11);
                    Log.LogMsg("DuplexBlockingTransit can't send bytes. OwningConnection is not connected.");
                    return;
                }

                if (isUDP)
                {
                    SocketDebug(12);
                    OwningConnection.MyUDPSocket.SendTo(data, OwningConnection.UDPSendTarget);
                    // Log.LogMsg("Testy UDP SEND COMPLETE. Is owning connection still alive? " + OwningConnection.IsAlive);
                }
                else
                {
                    //OwningConnection.MyTCPSocket.Blocking = true;
                    SocketDebug(15);
                    OwningConnection.MyTCPSocket.Send(data);
                    SocketDebug(16);
                }

                SocketDebug(17);
                OwningConnection.SentBytes(data);
                OwningConnection.PacketSent();
                SocketDebug(18);
            }
            catch (Exception e)
            {
                Log.LogMsg("Error SendBytes. " + e.Message);
                OwningConnection.KillConnection("Send error. " + e.Message);
            }
        }
        /// <summary>
        /// Serializes and sends a packet across the wire
        /// </summary>
        /// <param name="msg">The packet to send</param>
        public virtual int Send(Packet msg)
        {
            try
            {
                SocketDebug(29);
                if (msg.NeedsDeliveryAck)
                {
                    m_NumAcksWaitingFor++;
                }

                SocketDebug(30);
                byte[] raw = OwningConnection.SerializePacket(msg);
                SocketDebug(31);
                Log.LogMsg("Sending -> " + msg.GetType().ToString() + " (" + raw.Length.ToString() + " bytes)");
                Log.LogMsg("That message is " + raw.Length.ToString() + " bytes long");
                Log.LogMsg("1 Socket " + OwningConnection.MyTCPSocket.Handle.ToString() + "IsAlive=" + OwningConnection.MyTCPSocket.Connected.ToString() + ", with socket error reading " + m_LastTCPReceiveStatus.ToString());
                return(Send(raw, msg.Flags));
            }
            catch (Exception sendExc)
            {
                OwningConnection.KillConnection(sendExc.Message);
                return(-1);;
            }
        }
Пример #10
0
        /// <summary>
        /// Gets called when a send operation resolves.
        /// </summary>
        private void OnSendResolved(SocketAsyncEventArgs args, SockState state)
        {
            //// Log.LogMsg("Testy 13");
            try
            {
                OwningConnection.SentBytes(state.PacketBufferPointer.Position);
                bool isUDP = (state.Flags & PacketFlags.UDP) != 0;
                //Log.LogMsg("==>#### Async SEND Op Completed - #" + ((SockState)args.UserToken).ID.ToString() + "#");
                if (args.SocketError == SocketError.Success)
                {
                    //// Log.LogMsg("Testy 14");
                    state.PacketBufferPointer.Advance(args.BytesTransferred);
                    if (state.PacketBufferPointer.Position >= state.PacketBuffer.Length)
                    {
                        OwningConnection.PacketSent();
                        // Done sending packet.
                        state.Reset();
                        //Log.LogMsg("==>Done sending packet. Sent " + state.PacketBufferPointer.Position.ToString() + " bytes.");

                        // done sending packet, see if we have anything in the queue ready to go
                        bool             more  = false;
                        Queue <NetQItem> sendQ = isUDP ? m_SendQueueUDP : m_SendQueue;
                        lock (sendQ)
                        {
                            if (sendQ.Count > 0)
                            {
                                NetQItem itm = sendQ.Dequeue();
                                state.PacketBuffer = itm.Data;
                                state.Flags        = itm.Flags;
                                more = true;
                            }
                            else
                            {
                                // release the sending lock
                                if (isUDP)
                                {
                                    //Log.LogMsg("UDP send queue emptied.");
                                    Interlocked.Exchange(ref m_SendingUDP, 0);
                                }
                                else
                                {
                                    //Log.LogMsg("TCP send queue emptied.");
                                    Interlocked.Exchange(ref m_Sending, 0);
                                }
                            }
                        }

                        if (more)
                        {
                            //// Log.LogMsg("Testy 15");
                            SendBuffer(args, state, isUDP);
                        }

                        return;
                    }
                    else
                    {
                        //// Log.LogMsg("Testy 16");
                        // not done sending.  send again.
                        //Log.LogMsg("==>Continuing send.  " + state.PacketBufferPointer.Position.ToString() + " / " + state.PacketBuffer.Length.ToString() + " sent so far.");
                        SendBuffer(args, state, isUDP);
                    }
                }
                else
                {
                    //If we are in this else-statement, there was a socket error.
                    OwningConnection.KillConnection("Error sending packet. " + args.SocketError.ToString());
                }
            }
            catch (Exception ex)
            {
                //// Log.LogMsg("Testy 17");
                Log.LogMsg("Failed to ProcessSend. " + ex.Message);
                OwningConnection.KillConnection("Send error. " + ex.Message);
            }
        }
Пример #11
0
        /// <summary>
        /// We dont usually send everything all at once in the buffer.  This method sends what's in the buffer out in a piece by piece fashion.
        /// </summary>
        private void SendBuffer(SocketAsyncEventArgs args, SockState state, bool isUDP)
        {
            try
            {
#if !SILVERLIGHT
                //Log.LogMsg("==>$$$$ Async SEND op started - #" + ((SockState)args.UserToken).ID.ToString() + "#");
                if (!OwningConnection.BlockingMode)
#endif
                {
                    int toSend = state.PacketBuffer.Length - state.PacketBufferPointer.Position;
                    if (toSend > state.BufferBlockLength)
                    {
                        toSend = state.BufferBlockLength;
                    }

                    args.SetBuffer(state.BufferBlockOffset, toSend);
                    Util.Copy(state.PacketBuffer, state.PacketBufferPointer.Position, args.Buffer, state.BufferBlockOffset, toSend);

                    Socket socket = OwningConnection.MyTCPSocket;
#if !SILVERLIGHT
                    if (isUDP)
                    {
                        socket = OwningConnection.MyUDPSocket;
                        //Log.LogMsg("UDP Send Target = " + SendTarget.ToString());
                        args.RemoteEndPoint = OwningConnection.UDPSendTarget;
                        if (!socket.SendToAsync(args))
                        {
                            //// Log.LogMsg("Testy 7");
                            OnSendResolved(args, state);
                        }
                    }
                    else
#endif
                    {
                        if (!socket.SendAsync(args))
                        {
                            //// Log.LogMsg("Testy 8");
                            OnSendResolved(args, state);
                        }
                    }
                }
#if !SILVERLIGHT
                else
                {
                    if (isUDP)
                    {
                        //// Log.LogMsg("Testy 9");
                        OwningConnection.MyUDPSocket.SendTo(state.PacketBuffer, OwningConnection.UDPSendTarget);
                    }
                    else
                    {
                        //// Log.LogMsg("Testy 10");
                        OwningConnection.MyTCPSocket.Blocking = true;
                        OwningConnection.MyTCPSocket.Send(state.PacketBuffer);
                    }

                    //// Log.LogMsg("Testy 11");
                    OwningConnection.SentBytes(state.PacketBuffer);
                    OwningConnection.PacketSent();
                }
#endif
            }
            catch (Exception e)
            {
                //// Log.LogMsg("Testy 12");
                Log.LogMsg("Error SendBuffer. " + e.Message);
                OwningConnection.KillConnection("Send error. " + e.Message);
            }
        }
Пример #12
0
        /// <summary>
        /// Sends arbitrary bytes of data across the wire.  Note that if the remote endpoint can't decipher the data
        /// as a known packet, the connection will be dropped by that endpoint immediately.
        /// </summary>
        /// <param name="data">bytes to send</param>
        public virtual int Send(byte[] data, PacketFlags flags)
        {
            //Log.LogMsg("@__@ Monitor Enter");
            if (!OwningConnection.IsAlive)
            {
                //// Log.LogMsg("Testy 3");
                return(-1);
            }

            //Log.LogMsg("==>Sending " + data.Length.ToString() + " bytes.");
            try
            {
                bool isUDP = (flags & PacketFlags.UDP) != 0;

#if SILVERLIGHT
                // Silverlight can't do UDP and it can only send Async, i.e. Non-Blocking
                isUDP = false;
                OwningConnection.BlockingMode = false;
#endif
                if (isUDP)
                {
                    //// Log.LogMsg("Testy 4");
                    if (!OwningConnection.CanSendUDP)
                    {
                        Log.LogMsg("!!! Tried sending UDP packet when the connection wasn't yet ready to send UDP. Dropping packet.");
                        return(0);
                    }

                    // Don't allow fragmenting UDP packets
                    if (data.Length > m_SendArgsUDP.Buffer.Length && data.Length > 1024)
                    {
                        Log.LogMsg("Message exceeded UDP size. Sending via TCP instead.");
                        flags &= ~PacketFlags.UDP;
                    }
                }

                if (!OwningConnection.BlockingMode)
                {
                    // send via asyncsend, but only one send op can be in progress at one time
                    // out of order packets can happen because the actual send is done with I/O completion ports and if multiple
                    // packets get submitted to the I/O queue they could be processed out of order, especially if the packet are of wildly differing sizes
                    if (isUDP)
                    {
                        //// Log.LogMsg("Testy 5");
                        lock (m_SendQueueUDP)
                        {
                            if (1 == Interlocked.Exchange(ref m_SendingUDP, 1))
                            {
                                // failed to get the lock - a message is in progress.  queue message.
                                NetQItem qi = new NetQItem();
                                qi.Flags = flags;
                                qi.Data  = data;
                                m_SendQueueUDP.Enqueue(qi);
                                Log.LogMsg("Queueing UDP packet. Now " + m_SendQueueUDP.Count.ToString() + " in Queue.");
                                return(1);
                            }
                            //Log.LogMsg("Acquired UDP send lock.");
                        }
                    }
                    else
                    {
                        lock (m_SendQueue)
                        {
                            if (1 == Interlocked.Exchange(ref m_Sending, 1))
                            {
                                // failed to get the lock - a message is in progress.  queue message.
                                NetQItem qi = new NetQItem();
                                qi.Flags = flags;
                                qi.Data  = data;
                                m_SendQueue.Enqueue(qi);
                                Log.LogMsg("Queueing TCP packet. Now " + m_SendQueue.Count.ToString() + " in Queue.");
                                return(1);
                            }
                            //Log.LogMsg("Acquired TCP send lock.");
                        }
                    }
                }

                SocketAsyncEventArgs args  = isUDP ? m_SendArgsUDP : m_SendArgs;
                SockState            state = args.UserToken as SockState;
                state.Flags        = flags;
                state.PacketBuffer = data;
                //// Log.LogMsg("Testy 6");
                SendBuffer(args, state, isUDP);
            }
            catch (Exception sendExc)
            {
                OwningConnection.KillConnection(sendExc.Message);
                return(-1);;
            }

            return(1);
        }