예제 #1
0
        private void ReceiveCallback(IAsyncResult target)
        {
            Logger.WriteLine("--- ReceiveCallback");
            Message.MessageType requestType = Message.MessageType.Unknown;
            Socket handler = null;
            try
            {
                object[] obj = new object[2];
                obj = (object[])target.AsyncState;

                byte[] buffer = (byte[]) obj[0];
                handler = (Socket) obj[1];

                Logger.WriteLine("ReceiveCallback from " + (handler.RemoteEndPoint as IPEndPoint).Address + ":" + (handler.RemoteEndPoint as IPEndPoint).Port);

                bool quit = false;

                int bytesRead = handler.EndReceive(target);
                if (bytesRead > 0)
                {
                    Message request = new Message(buffer);
                    Message response;

                    requestType = request.GetMessageType();
                    if (requestType == Message.MessageType.HandshakePeerCreator) // Peer client mau join ke room ini
                    {
                        #region Handshake
                        Logger.WriteLine("HandshakePeerCreator");
                        if (Room.Members.Count < Room.MaxPlayer)
                        {
                            int newPeerId, newPeerListenPort;
                            IPAddress newPeerIp = (handler.RemoteEndPoint as IPEndPoint).Address;
                            request.GetHandshakePeerCreator(out newPeerId, out newPeerListenPort);
                            Room.Members.Add(new Peer(newPeerId, newPeerIp, newPeerListenPort));

                            Logger.WriteLine("Peer ID : " + newPeerId);
                            Logger.WriteLine("Peer IP : " + newPeerIp + ":" + newPeerListenPort);

                            // Send SUCCESS message
                            response = Message.CreateMessageSuccess();
                            handler.Send(response.data, 0, response.data.Length, SocketFlags.None);

                            if (nextPeerSocket != null)
                            {
                                Logger.WriteLine("Sending NEW MEMBER to nextPeerSocket: " + (nextPeerSocket.RemoteEndPoint as IPEndPoint).Address + ":" + (nextPeerSocket.RemoteEndPoint as IPEndPoint).Port);
                                // Send NewMember message to next peer
                                response = Message.CreateMessageNewMember(newPeerId, (handler.RemoteEndPoint as IPEndPoint).Address, newPeerListenPort);
                                nextPeerSocket.Send(response.data, 0, response.data.Length, SocketFlags.None);
                            }
                            else
                            {
                                IPEndPoint ipEndPoint = new IPEndPoint(newPeerIp, newPeerListenPort);
                                nextPeerSocket = new Socket(
                                    newPeerIp.AddressFamily,
                                    SocketType.Stream,
                                    ProtocolType.Tcp
                                   );
                                nextPeerSocket.NoDelay = false;
                                nextPeerSocket.Connect(ipEndPoint);

                                Logger.WriteLine("Setting up nextPeerSocket to " + (nextPeerSocket.RemoteEndPoint as IPEndPoint).Address + ":" + (nextPeerSocket.RemoteEndPoint as IPEndPoint).Port);

                                response = Message.CreateMessageRoomModel(Room);
                                nextPeerSocket.Send(response.data, 0, response.data.Length, SocketFlags.None);
                                Logger.WriteLine("Send room info");

                                keepAliveRoom = new Thread(new ThreadStart(SendAliveNextPeer));
                                keepAliveRoom.Start();
                            }

                            response = Message.CreateMessageAdd(newPeerId, Room.RoomId);
                            lock (trackerPaddle)
                            {
                                trackerSocket.Send(response.data, 0, response.data.Length, SocketFlags.None);
                                byte[] bufferRecv = new byte[1024];
                                trackerSocket.Receive(bufferRecv, 0, bufferRecv.Length, SocketFlags.None);
                            }
                        }
                        else
                        {
                            Logger.WriteLine("Send FAILED: Room penuh");
                            // Send FAILED message akibat ruang penuh
                            response = Message.CreateMessageFailed();
                            handler.Send(response.data, 0, response.data.Length, SocketFlags.None);
                            handler.Close();
                            quit = true;
                        }
                        #endregion
                    }
                    else if (requestType == Message.MessageType.KeepAlive)
                    {
                        #region Keep Alive
                        int peerId;
                        request.GetKeepAlive(out peerId);
                        Peer peer = Room.Members.Find(fpeer => fpeer.PeerId == peerId);
                        if (peer != null)
                        {
                            //Send KeepAlive Message back
                            response = request;
                            handler.Send(response.data, 0, response.data.Length, SocketFlags.None);
                        }
                        else
                        {
                            response = Message.CreateMessageFailed();
                            handler.Send(response.data, 0, response.data.Length, SocketFlags.None);
                        }
                        #endregion
                    }
                    else if (requestType == Message.MessageType.NewMember)
                    {
                        #region NewMember
                        Logger.WriteLine("NewMember");
                        if (IsCreator)
                        {
                            Logger.WriteLine("NewMember has been received by peer creator");
                            Logger.WriteLine("Closing connection from " + (handler.RemoteEndPoint as IPEndPoint).Address + ":" + (handler.RemoteEndPoint as IPEndPoint).Port);
                            handler.Close();
                            quit = true;
                        }
                        else
                        {
                            bool isLast = Room.Members.Last().PeerId == PeerId;

                            int newPeerId, newPeerListenPort;
                            IPAddress newPeerIp;
                            request.GetNewMember(out newPeerId, out newPeerIp, out newPeerListenPort);
                            Room.Members.Add(new Peer(newPeerId, newPeerIp, newPeerListenPort));

                            Logger.WriteLine("Sending NEW MEMBER to nextPeerSocket: " + (nextPeerSocket.RemoteEndPoint as IPEndPoint).Address + ":" + (nextPeerSocket.RemoteEndPoint as IPEndPoint).Port);
                            response = request;
                            nextPeerSocket.Send(response.data, 0, response.data.Length, SocketFlags.None);

                            if (isLast)
                            {
                                Logger.WriteLine("Closing connection " + (nextPeerSocket.RemoteEndPoint as IPEndPoint).Address + ":" + (nextPeerSocket.RemoteEndPoint as IPEndPoint).Port);
                                nextPeerSocket.Close();

                                IPEndPoint ipEndPoint = new IPEndPoint(newPeerIp, newPeerListenPort);
                                nextPeerSocket = new Socket(
                                    newPeerIp.AddressFamily,
                                    SocketType.Stream,
                                    ProtocolType.Tcp
                                   );

                                nextPeerSocket.NoDelay = false;
                                nextPeerSocket.Connect(ipEndPoint);

                                Logger.WriteLine("Setting up nextPeerSocket to " + (nextPeerSocket.RemoteEndPoint as IPEndPoint).Address + ":" + (nextPeerSocket.RemoteEndPoint as IPEndPoint).Port);

                                response = Message.CreateMessageRoomModel(Room);
                                nextPeerSocket.Send(response.data, 0, response.data.Length, SocketFlags.None);
                                Logger.WriteLine("Send room info");
                            }
                        }
                        #endregion
                    }
                    else if (requestType == Message.MessageType.RoomModel)
                    {
                        #region Room
                        Logger.WriteLine("RoomModel");
                        Room room;
                        request.GetRoomModel(out room);
                        Room = room;
                        #endregion
                    }
                    else if (requestType == Message.MessageType.Quit)
                    {
                        int peerId;
                        request.GetQuit(out peerId);
                        Peer peer = Room.Members.Find(fpeer => fpeer.PeerId == peerId);
                        byte[] bufferRecv;

                        if (Room.Members.Count != 2)
                        {
                            if (PeerId == peerId)
                            {
                                Logger.WriteLine("Quit done");
                            }
                            else
                            {
                                int i = 0;
                                for (; i < Room.Members.Count; i++)
                                {// i adalah indeks peer yang ingin quit
                                    if (Room.Members[i].PeerId == peerId)
                                    {
                                        break;
                                    }
                                }

                                int j = 0;
                                for (; j < Room.Members.Count; j++)
                                {// j adalah indeks current peer
                                    if (Room.Members[j].PeerId == PeerId)
                                    {
                                        break;
                                    }
                                }

                                if (j == i + 1 || (j == 0 && i == Room.Members.Count - 1)) // yg mau quit adalah peer sebelum current peer
                                {
                                    quit = true;
                                }

                                response = request;

                                lock (nextPeerPaddle)
                                {
                                    nextPeerSocket.Send(response.data, 0, response.data.Length, SocketFlags.None);
                                    Logger.WriteLine("Forward Quit to " + (nextPeerSocket.RemoteEndPoint as IPEndPoint).Address);
                                    bufferRecv = new byte[1024];
                                    nextPeerSocket.Receive(bufferRecv, 0, bufferRecv.Length, SocketFlags.None);
                                }

                                if (i == j + 1 || (i == 0 && j == Room.Members.Count - 1))// yg mau quit adalah peer setelah current peer
                                {
                                    nextPeerSocket.Close();
                                    IPAddress ip = Room.Members[(i + 1) % (Room.Members.Count - 1)].IPAddress;
                                    IPEndPoint ipEndPoint = new IPEndPoint(ip, Room.Members[(i + 1) % (Room.Members.Count - 1)].ListeningPort);
                                    nextPeerSocket = new Socket(
                                        ip.AddressFamily,
                                        SocketType.Stream,
                                        ProtocolType.Tcp
                                        );

                                    nextPeerSocket.NoDelay = false;
                                    nextPeerSocket.Connect(ipEndPoint);

                                    nextPeerSocket = null;
                                }

                                if (this.PeerId == Room.Creator.PeerId || (peerId == Room.Creator.PeerId && Room.Members[1].PeerId == this.PeerId))
                                {
                                    lock (trackerPaddle)
                                    {
                                        response = Message.CreateMessageRemove(peerId, PeerId, Configuration.ListenPort, Room.RoomId);
                                        trackerSocket.Send(response.data, 0, response.data.Length, SocketFlags.None);

                                        bufferRecv = new byte[1024];
                                        trackerSocket.Receive(bufferRecv, 0, bufferRecv.Length, SocketFlags.None);
                                    }
                                }

                                if (peerId == Room.Creator.PeerId)
                                {
                                    Room.Creator = Room.Members[1];
                                }

                                response = Message.CreateMessageSuccess();
                                handler.Send(response.data, 0, response.data.Length, SocketFlags.None);

                                bufferRecv = new byte[1024];
                                nextPeerSocket.Receive(bufferRecv, 0, bufferRecv.Length, SocketFlags.None);
                            }
                        }
                        else
                        {
                            lock (trackerPaddle)
                            {
                                response = Message.CreateMessageRemove(peerId, PeerId, Configuration.ListenPort, Room.RoomId);
                                trackerSocket.Send(response.data, 0, response.data.Length, SocketFlags.None);

                                bufferRecv = new byte[1024];
                                trackerSocket.Receive(bufferRecv, 0, bufferRecv.Length, SocketFlags.None);
                            }
                        }
                        Room.Members.Remove(peer);
                    }
                    else if (requestType == Message.MessageType.Start)
                    {
                        #region Start
                        Logger.WriteLine("Start");
                        int peerId;
                        string roomId;
                        request.GetStart(out peerId, out roomId);

                        Logger.WriteLine("Received START message with PeerId : " + peerId + " RoomId : " + roomId);

                        if (peerId == PeerId)
                        {
                            // do nothing
                            Logger.WriteLine("FINISHED");
                        }
                        else
                        {
                            // Send NewMember message to next peer
                            response = request;
                            nextPeerSocket.Send(response.data, 0, response.data.Length, SocketFlags.None);
                            Logger.WriteLine("Forward START to " + (nextPeerSocket.RemoteEndPoint as IPEndPoint).Address);
                        }
                    }
                    else
                    {
                        Logger.WriteLine("Listener receive unknown message");
                        // Send FAILED message akibat ruang penuh
                        response = Message.CreateMessageFailed();
                        handler.Send(response.data, 0, response.data.Length, SocketFlags.None);
                    }
                        #endregion
                }

                if (!quit)
                {
                    IAsyncResult nextAsyncResult = handler.BeginReceive(
                        buffer,
                        0,
                        buffer.Length,
                        SocketFlags.None,
                        new AsyncCallback(ReceiveCallback),
                        obj
                    );

                    if (!nextAsyncResult.AsyncWaitHandle.WaitOne(Configuration.MaxTimeout))
                    {
                        Logger.WriteLine("Connection timeout for peer with IP Address " + (handler.LocalEndPoint as IPEndPoint).Address + ":" + (handler.LocalEndPoint as IPEndPoint).Port + " -> " + (handler.RemoteEndPoint as IPEndPoint).Address + ":" + (handler.RemoteEndPoint as IPEndPoint).Port);
                        Logger.WriteLine("Closing connection " + (handler.RemoteEndPoint as IPEndPoint).Address + ":" + (handler.RemoteEndPoint as IPEndPoint).Port);
                        handler.Close();
                    }
                }
            }
            catch (SocketException exc)
            {
                Logger.WriteLine(exc);
                if (exc.SocketErrorCode == SocketError.HostDown || exc.SocketErrorCode == SocketError.ConnectionReset)
                {
                    if (Room.Members.Count > 2)
                    {
                        int index = -1;
                        for (int i = 0; i < Room.Members.Count; i++)
                        {
                            Peer p = Room.Members[i];
                            if (p.IPAddress.Equals((handler.LocalEndPoint as IPEndPoint).Address))
                            {
                                index = i;
                            }
                        }

                        if (index == 0)
                        {
                            index = Room.Members.Count - 2;
                        }
                        else
                        {
                            index--;
                        }

                        Peer backPeer = Room.Members[index];
                        byte[] buffer = new byte[1024];
                        Message request = Message.CreateMessageQuit(backPeer.PeerId);
                        lock (nextPeerPaddle)
                        {
                            nextPeerSocket.Send(request.data, 0, request.data.Length, SocketFlags.None);
                            nextPeerSocket.Receive(buffer, 0, buffer.Length, SocketFlags.None);
                        }
                    }
                    else
                    {
                        // Remove last element
                        Room.Members.RemoveAt(1);
                        lock (nextPeerPaddle)
                        {
                            nextPeerSocket = null;
                        }
                    }
                }
            }

            Logger.WriteLine();
        }
예제 #2
0
        public void ReceiveCallback(IAsyncResult target)
        {
            try
            {
                object[] obj = new object[2];
                obj = (object[])target.AsyncState;

                byte[] data = (byte[])obj[0];
                Socket handler = (Socket)obj[1];
                IPAddress tempIP = (handler.RemoteEndPoint as IPEndPoint).Address;

                string content = string.Empty;
                int bytesRead = handler.EndReceive(target);

                if (bytesRead > 0)
                {
                    Message request = new Message(data);
                    Message response;

                    Message.MessageType requestType = request.GetMessageType();
                    if (requestType == Message.MessageType.HandshakePeer)
                    {
                        #region Handshake
                        Logger.WriteLine("New peer with IP Address " + (handler.RemoteEndPoint as IPEndPoint).Address.ToString() + " request handshake.");

                        if (peers.Count < Configuration.MaxPeer)
                        {
                            int newPeerId = GenerateNewPeerId();
                            Peer peer = new Peer(newPeerId, (handler.RemoteEndPoint as IPEndPoint).Address);
                            peers.Add(newPeerId, peer);

                            Logger.WriteLine("Peer with IP Address " + (handler.RemoteEndPoint as IPEndPoint).Address.ToString() + " registered with ID " + newPeerId + ".");
                            Logger.WriteLine(peer);
                            Logger.WriteLine();

                            // send handshake response with ID
                            response = Message.CreateMessageHandshakeTracker(newPeerId);
                            handler.Send(response.data, 0, response.data.Length, SocketFlags.None);
                        }
                        else
                        {
                            // send handshake response with ID
                            response = Message.CreateMessageFailed();
                            handler.Send(response.data, 0, response.data.Length, SocketFlags.None);
                        }
                        #endregion
                    }
                    else if (requestType == Message.MessageType.KeepAlive)
                    {
                        #region Keep Alive
                        int peerId;
                        Peer peer;
                        request.GetKeepAlive(out peerId);
                        if (peers.TryGetValue(peerId, out peer))
                        {
                            Logger.WriteLine("Keep alive is sent by Peer: " + peer);

                            // send KEEP ALIVE message back
                            response = request;
                            handler.Send(response.data, 0, response.data.Length, SocketFlags.None);
                        }
                        else
                        {
                            // send FAIL message that peer is not registered
                            response = Message.CreateMessageFailed();
                            handler.Send(response.data, 0, response.data.Length, SocketFlags.None);
                        }
                        #endregion
                    }
                    else if (requestType == Message.MessageType.CreateRoom)
                    {
                        #region Create Room
                        int peerId, maxPlayers, listenPort;
                        string roomId;
                        request.GetCreate(out peerId, out maxPlayers, out roomId, out listenPort);

                        Peer peer;
                        if (peers.TryGetValue(peerId, out peer))
                        {
                            Room room;
                            if (!rooms.TryGetValue(roomId, out room))
                            {
                                room = new Room(roomId, peer, maxPlayers, listenPort);
                                rooms.Add(roomId, room);
                                Logger.WriteLine("Create room request is sent by peer " + peer + " for room " + room);

                                // send reply message SUCCESS
                                response = Message.CreateMessageSuccess();
                                handler.Send(response.data, 0, response.data.Length, SocketFlags.None);
                            }
                            else
                            {
                                // send message FAIL that room doesn't exist
                                response = Message.CreateMessageFailed();
                                handler.Send(response.data, 0, response.data.Length, SocketFlags.None);
                            }
                        }
                        else
                        {
                            // send message FAIL that peer is not registered
                            response = Message.CreateMessageFailed();
                            handler.Send(response.data, 0, response.data.Length, SocketFlags.None);
                        }
                        #endregion
                    }
                    else if (requestType == Message.MessageType.ListRoom)
                    {
                        #region List Room
                        int peerId;
                        request.GetList(out peerId);

                        Peer peer;
                        if (peers.TryGetValue(peerId, out peer) && !peer.InRoom)
                        {
                            Logger.WriteLine("List room is sent to Peer " + peer);
                            List<Message.MessageRoomBody> listRooms = new List<Message.MessageRoomBody>();
                            foreach (var r in rooms.Values)
                            {
                                Message.MessageRoomBody mb;
                                mb.roomId = r.Id;
                                mb.maxPlayers = r.MaxPlayers;
                                mb.currentPlayer = r.Members.Count;
                                listRooms.Add(mb);
                            }

                            // send ROOM message
                            response = Message.CreateMessageRoom(listRooms);
                            handler.Send(response.data, 0, response.data.Length, SocketFlags.None);
                        }
                        else
                        {
                            // send message FAIL that peer is not registered
                            response = Message.CreateMessageFailed();
                            handler.Send(response.data, 0, response.data.Length, SocketFlags.None);
                        }
                        #endregion
                    }
                    else if (requestType == Message.MessageType.Join)
                    {
                        #region Join Room
                        int peerId;
                        string roomId;
                        request.GetJoin(out peerId, out roomId);
                        Peer peer;
                        if (peers.TryGetValue(peerId, out peer) && !peer.InRoom)
                        {
                            Room room;
                            if (rooms.TryGetValue(roomId, out room) && room.Members.Count < room.MaxPlayers)
                            {
                                Logger.WriteLine("Join room request is sent by Peer " + peer + " for Room " + room);

                                // send IP address back to peer
                                response = Message.CreateMessageCreatorInfo(room.Creator.IpAddress, room.ListenPort);
                                handler.Send(response.data, 0, response.data.Length, SocketFlags.None);
                            }
                            else
                            {
                                // send message FAIL that peer is not registered
                                response = Message.CreateMessageFailed();
                                handler.Send(response.data, 0, response.data.Length, SocketFlags.None);
                            }
                        }
                        else
                        {
                            // send message FAIL that peer is not registered
                            response = Message.CreateMessageFailed();
                            handler.Send(response.data, 0, response.data.Length, SocketFlags.None);
                        }
                        #endregion
                    }
                    else if (requestType == Message.MessageType.Start)
                    {
                        #region Start
                        int peerId;
                        request.GetList(out peerId);
                        Peer peer;
                        if (peers.TryGetValue(peerId, out peer) && !peer.InRoom)
                        {

                        }
                        else
                        {
                            // send message FAIL that peer is not registered
                            response = Message.CreateMessageFailed();
                            handler.Send(response.data, 0, response.data.Length, SocketFlags.None);
                        }
                        #endregion
                    }
                    else if (requestType == Message.MessageType.Quit)
                    {
                        #region Quit
                        int peerId;
                        request.GetList(out peerId);
                        Peer peer;
                        if (peers.TryGetValue(peerId, out peer) && !peer.InRoom)
                        {

                        }
                        else
                        {
                            // send message FAIL that peer is not registered
                            response = Message.CreateMessageFailed();
                            handler.Send(response.data, 0, response.data.Length, SocketFlags.None);
                        }
                        #endregion

                        //}
                        //else if (requestType == Message.MessageType.Add)
                        //{
                        //    #region Add
                        //    int peerId;
                        //    request.GetList(out peerId);
                        //    Peer peer;
                        //    if (peers.TryGetValue(peerId, out peer) && !peer.InRoom)
                        //    {
                        //        // ...
                        //    }
                        //    else
                        //    {
                        //        // send message FAIL that peer is not registered
                        //        response = Message.CreateMessageFailed();
                        //        handler.Send(response.data, 0, response.data.Length, SocketFlags.None);
                        //    }
                        //    #endregion
                    }
                    else if (requestType == Message.MessageType.Add)
                    {
                        #region Add
                        int peerId;
                        string roomId;
                        request.GetAdd(out peerId, out roomId);
                        Peer peer;
                        Room room;
                        if (peers.TryGetValue(peerId, out peer) && (rooms.TryGetValue(roomId, out room)))
                        {
                            room.AddPeer(peer);
                            response = Message.CreateMessageSuccess();
                            handler.Send(response.data, 0, response.data.Length, SocketFlags.None);
                        }
                        else
                        {
                            // send message FAIL that peer is not registered
                            response = Message.CreateMessageFailed();
                            handler.Send(response.data, 0, response.data.Length, SocketFlags.None);
                        }
                        #endregion
                    }
                    else if (requestType == Message.MessageType.Remove)
                    {
                        #region Remove
                        int peerId;
                        int creatorId;
                        int creatorPort;
                        string roomId;

                        request.GetRemove(out peerId, out creatorId, out creatorPort, out roomId);
                        Room room;
                        if (rooms.TryGetValue(roomId, out room))
                        {
                            room.RemovePeer(peerId);
                            Peer creator;
                            room.Members.TryGetValue(creatorId, out creator);
                            room.Creator = creator;
                            room.ListenPort = creatorPort;

                            response = Message.CreateMessageSuccess();
                            handler.Send(response.data, 0, response.data.Length, SocketFlags.None);
                        }
                        else
                        {
                            // send message FAIL that peer is not registered
                            response = Message.CreateMessageFailed();
                            handler.Send(response.data, 0, response.data.Length, SocketFlags.None);
                        }
                        #endregion
                    }
                    else
                    {
                        Logger.WriteLine("Unknown message received from " + (handler.RemoteEndPoint as IPEndPoint));
                        // throw message failed
                        response = Message.CreateMessageFailed();
                        handler.Send(response.data, 0, response.data.Length, SocketFlags.None);
                    }

                    #region Receive for Next Message
                    byte[] buffer = new byte[1024];
                    obj = new object[2];
                    obj[0] = buffer;
                    obj[1] = handler;
                    IAsyncResult nextAsyncResult = handler.BeginReceive(
                        buffer,
                        0,
                        buffer.Length,
                        SocketFlags.None,
                        new AsyncCallback(ReceiveCallback),
                        obj
                        );

                    if (!nextAsyncResult.AsyncWaitHandle.WaitOne(Configuration.MaxTimeout))
                    {
                        Logger.WriteLine("Connection timeout for peer with IP Address " + (handler.LocalEndPoint as IPEndPoint).Address + ":" + (handler.LocalEndPoint as IPEndPoint).Port + " -> " + (handler.RemoteEndPoint as IPEndPoint).Address + ":" + (handler.RemoteEndPoint as IPEndPoint).Port);

                        // find peer id
                        int peerId = 0;
                        foreach (KeyValuePair<int, Peer> entry in peers)
                        {
                            if (entry.Value.IpAddress.Equals((handler.RemoteEndPoint as IPEndPoint).Address))
                            {
                                peerId = entry.Key;
                                break;
                            }
                        }
                        peers.Remove(peerId);

                        handler.Close();
                    }
                    #endregion
                }
            }
            catch (SocketException exc)
            {
                Logger.WriteLine(exc);
            }
        }