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(); }
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); } }