Beispiel #1
0
        /// <summary>
        /// Выполняет одноразовую операцию получения и отправки пакетов.
        /// </summary>
        public override void Process()
        {
            // Flush send buffer
            OSCARQueueEntity toSend;
            while (!m_sendBuffer.IsEmpty)
                if (m_sendBuffer.TryDequeue(out toSend))
                    sendPacket(toSend.Host, ref toSend.FLAP, toSend.Data);
                else
                    break;

            // Receive packets
            byte[] data;
            EndPoint from;
            while (this.readPacket(ref m_svcFlap, out data, out from))
                HandlePacket(ref m_svcFlap, data, (IPEndPoint)from);

            // Check connect attempt
            if (m_connReq != null) // IsConnecting
            {
                // Did connection attempt failed (No response?)
                if ((Environment.TickCount - m_connReq.LastSent) >= ConnReq.Timeout)
                {
                    // Did we reached fail limit?
                    if (m_connReq.AttemptsTaken >= ConnReq.AttemptsLimit)
                    {
                        var host = m_connReq.Host;
                        var error = new TimeoutException("OSCARUdp connection attempt timed out, response was not received.");
                        m_connReq = null;
                        m_events.ConnectFailed(this, new HostErrorEventArgs(host, error));
                    }
                    else
                    {
                        // Re-send
                        m_connReq.Send(this, ref m_svcFlap);
                    }
                }
            }
        }
Beispiel #2
0
        private void HandlePacket(ref FLAPHeader flap, byte[] data, IPEndPoint from)
        {
            var tlvs = (TLVChain)data;
            var type = tlvs[SvcLayer.TLV_TYPE].Value[0];
            switch(type)
            {
                case SvcLayer.TYPE_USER_DATA:
                    if (Connections.Contains(from))
                        m_events.TriggerPacketReceived(this, new PacketEventArgs(from, ref flap, tlvs[SvcLayer.TLV_USER_DATA].Value));
                    break;

                case SvcLayer.TYPE_CONNECT_ACCEPT:
                    if (IsConnecting
                        && m_connReq.Host.Equals(from)
                        && Misc.CompareByteArrays(m_connReq.Hash, tlvs[SvcLayer.TLV_CONNECT_HASH].Value))
                    {
                        m_connReq = null;
                        Connections.Add(from);
                        m_events.Connected(this, new HostConnectEventArgs(from, true));
                    }
                    break;

                case SvcLayer.TYPE_CONNECT_REQST:
                    if (m_acceptsIncomingConnections
                        && (!this.IsConnecting || m_connReq.Host != from)
                        && m_events.AuthorizeIncomingConnection(this, new HostEventArgs(from))
                        && !this.Connections.Contains(from))
                    {
                        var tosend = new TLVChain(2)
                        {
                            new TLV { TypeID = SvcLayer.TLV_TYPE, Value = new byte[1] { SvcLayer.TYPE_CONNECT_ACCEPT } },
                            new TLV { TypeID = SvcLayer.TLV_CONNECT_HASH, Value = tlvs[SvcLayer.TLV_CONNECT_HASH].Value }
                        };
                        sendPacket(from, ref flap, (byte[])tosend);

                        Connections.Add(from);
                        m_events.Connected(this, new HostConnectEventArgs(from, false));
                    }
                    break;
            }
        }
Beispiel #3
0
        /// <summary>
        /// Запускает попытку исходящего подключения к удаленному хосту.
        /// </summary>
        /// <param name="to">Удаленный узел для подключения</param>
        /// <param name="async">Значение False заблокирует исполнение программы до окончания исходящего подключения</param>
        public override void Connect(EndPoint to, bool async = true)
        {
            if (this.IsConnecting)
                throw new InvalidOperationException("There is already active outgoing connect attempt in progress.");
            else if(this.Connections.Contains(to))
                throw new ArgumentException("This address is already connected to current peer!");

            m_connReq = new ConnReq(to);
            m_connReq.Send(this, ref m_svcFlap);
            m_events.ConnectStarted(this, new HostEventArgs(to));

            if (!async)
                while (this.IsConnecting)
                    Thread.Sleep(50);
        }