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 bool CreateRoom(string roomId, int maxPlayers) { try { if (IsConnected && !IsInRoom) { Logger.WriteLine("Requesting to create room"); byte[] buffer = new byte[1024]; Message request = Message.CreateMessageCreate(PeerId, maxPlayers, roomId, Configuration.ListenPort); lock (trackerPaddle) { trackerSocket.Send(request.data, 0, request.data.Length, SocketFlags.None); trackerSocket.Receive(buffer, buffer.Length, SocketFlags.None); } Message response = new Message(buffer); Message.MessageType responseType = response.GetMessageType(); if (responseType == Message.MessageType.Success) { Logger.WriteLine("Request create room success: " + roomId); Room = new Room(roomId, new Peer(PeerId, (trackerSocket.LocalEndPoint as IPEndPoint).Address, Configuration.ListenPort), maxPlayers); Room.Members.Add(Room.Creator); IsInRoom = true; IsCreator = true; return true; } else if (responseType == Message.MessageType.Failed) { Logger.WriteLine("Request create room failed."); return false; } else { Logger.WriteLine("Response unrecognized."); return false; } } else if (!IsConnected) { Logger.WriteLine("Not connected to tracker, connect to tracker first."); return false; } else if (IsInRoom) { Logger.WriteLine("Currently in room, quit room first."); return false; } else { Logger.WriteLine("Unknown error."); return false; } } catch (Exception exc) { Logger.WriteLine(exc); return false; } }