package controllers; import static play.libs.F.Matcher.ClassOf; import static play.libs.F.Matcher.Equals; import static play.mvc.Http.WebSocketEvent.SocketClosed; import static play.mvc.Http.WebSocketEvent.TextFrame; import java.util.Map; import models.ChatRoom; import models.ChatRoomFactory; import models.chat.ChatPort; import models.chat.MerchantPort; import play.Logger; import play.Play; import play.data.validation.Required; import play.libs.F.Either; import play.libs.F.EventStream; import play.libs.F.Promise; import play.mvc.Controller; import play.mvc.Http.WebSocketClose; import play.mvc.Http.WebSocketEvent; import play.mvc.WebSocketController; public class WebSocket extends Controller { public static void room(String user) { render(user); } public static class ChatRoomSocket extends WebSocketController { private static String roomUserLimit = Play.configuration.getProperty("room.user.limit"); public static void join(@Required String user, @Required String uid, @Required String mid, @Required String image) { if (validation.hasErrors()) { renderJSON(false); } // Get chat room with mid Map<String, ChatRoom> rooms = ChatRoomFactory.rooms(); ChatRoom room = null; if (rooms.get(mid) == null) { room = new ChatRoom(mid); rooms.put(mid, room); // 创建MerchantPort对象 MerchantPort mp = new MerchantPort(); mp.port = Long.parseLong(Play.configuration.get("http.port").toString()); mp.mid = mid; mp.socketNumber = room.socketNumber; mp.save(); Logger.info("MerchantPort(mid:%s, port:%d) created", mp.mid,mp.port); ChatPort.updateRoomCount(rooms.size(), mp.port); Logger.info("Update rooms counts(%d) on port %d", rooms.size(), mp.port); } else { room = rooms.get(mid); } Logger.info("This server rooms counts are : %d. current room id is %s.", rooms.size(), room.mid); if (room.socketNumber >= Integer.parseInt(roomUserLimit)) { return; } // Socket connected, join the chat room EventStream<ChatRoom.Event> roomMessagesStream = room.join(user, uid, image); // Loop while the socket is open while (inbound.isOpen()) { // Wait for an event (either something coming on the inbound // socket channel, or ChatRoom messages) Either<WebSocketEvent, ChatRoom.Event> e = await(Promise.waitEither(inbound.nextEvent(), roomMessagesStream.nextEvent())); // Case: User typed 'quit' for (String userMessage : TextFrame.and(Equals("quit")).match(e._1)) { room.leave(user, uid, image); outbound.send("quit:ok"); disconnect(); } // Case: TextEvent received on the socket for (String userMessage : TextFrame.match(e._1)) { Logger.debug("Got message -> %s:%s:%s:%s", user, uid, image, userMessage); room.say(user, uid, image, userMessage); } // Case: Someone joined the room for (ChatRoom.Join joined : ClassOf(ChatRoom.Join.class).match(e._2)) { outbound.send("join:%s", joined.user); } // Case: New message on the chat room for (ChatRoom.Message message : ClassOf(ChatRoom.Message.class).match(e._2)) { outbound.send("message:%s:%s:%s:%s", message.user, message.uid, message.image, message.text); } // Case: Someone left the room for (ChatRoom.Leave left : ClassOf(ChatRoom.Leave.class).match(e._2)) { // Logger.debug("leave:%s", left.user); outbound.send("leave:%s", left.user); } // Case: The socket has been closed for (WebSocketClose closed : SocketClosed.match(e._1)) { room.leave(user, uid, image); disconnect(); } } } } }