Пример #1
0
        public static void Receive_Callback(IAsyncResult result)
        {
            StunSession session = (StunSession)result.AsyncState;
            Socket      socket  = session.TcpSocket;

            int read = socket.EndReceive(result);

            if (read > 0)
            {
                session.Position += read;

                // if we have at least 4 bytes we can check the length
                if (session.Position > 3)
                {
                    // extract length and compare with buffer position, we may have a full message
                    byte[] lengthBytes = new byte[2];
                    Array.Copy(session.SocketBuffer, 2, lengthBytes, 0, 2);

                    if (BitConverter.IsLittleEndian)
                    {
                        Array.Reverse(lengthBytes);
                    }

                    ushort length = BitConverter.ToUInt16(lengthBytes, 0);
                    if (length + 20 == session.Position)
                    {
                        StunMessage message = new StunMessage(session.SocketBuffer);

                        // TODO: work out how to process message :)
                        // we're now on a secondary thread in a static method, with no access to the "server"
                    }
                    else
                    {
                        session.TcpSocket.BeginReceive(session.SocketBuffer, session.Position, session.SocketBuffer.Length - session.Position, SocketFlags.None, new AsyncCallback(Receive_Callback), session);
                    }
                }
            }
            else
            {
                socket.Close();
            }
        }
Пример #2
0
        public void Start()
        {
            TcpListener tcpServer = new TcpListener(IPAddress.Parse(options.ListenAddress), options.TcpPort);
            UdpClient   udpClient = new UdpClient(new IPEndPoint(IPAddress.Parse(options.ListenAddress), options.UdpPort));

            Task[]             tasks    = new Task[2]; // UDP receive, TCP accept
            List <StunSession> sessions = new List <StunSession>();

            // TODO: this is taken from an console app I used for UDP testing, refactor
            // Task t = Task.Run(async () =>
            // {
            while (true)
            {
                // TODO: need to add logic to manage tasks for when UDP and/or TCP requests come in
                // if the tasks are not already outstanding (i.e. awaiting from a previous loop) then
                // add, otherwise just check for completion

                // if task is already outstanding there is nothing to do but check if it's complete
                if (tasks[0] == null)
                {
                    tasks[0] = udpClient.ReceiveAsync();
                }

                if (tasks[1] == null)
                {
                    tasks[2] = tcpServer.AcceptSocketAsync();
                }

                // check for any new connections
                int task = Task.WaitAny(tasks, 5);
                if (task == 0)
                {
                    // UDP client sent a request
                    UdpReceiveResult result = ((Task <UdpReceiveResult>)tasks[0]).Result;

                    // done with the task so null it ready for next loop iteration
                    tasks[0] = null;

                    // TODO: store this somewhere for future reference
                    IPEndPoint remoteEndpoint = result.RemoteEndPoint;

                    // TODO: add some validation of magic number, 32-bit alignment etc.
                    byte[]      buffer  = result.Buffer;
                    StunMessage message = new StunMessage(buffer);

                    // process the message
                    ProcessMessage(message);
                }
                else if (task == 1)
                {
                    // accepting a connection - create a new session object and start tracking
                    StunSession session = new StunSession();
                    sessions.Add(session);

                    session.TcpSocket = ((Task <Socket>)tasks[1]).Result;

                    // done with the task so null it ready for next loop iteration
                    tasks[1] = null;

                    // add task to receive TCP packet
                    // tcpReceiveTasks.Add(session.TcpSocket.ReceiveAsync(session.SocketBuffer, SocketFlags.None));
                    session.TcpSocket.BeginReceive(session.SocketBuffer, session.Position, session.SocketBuffer.Length - session.Position, SocketFlags.None, new AsyncCallback(Receive_Callback), session);
                }
            }
            // });

            // Console.WriteLine("Press any key to quit it");
            // Console.ReadKey();
        }