package com.moshi.push.recepsrv.session; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import io.netty.channel.Channel; import com.moshi.push.recepsrv.conf.RecepsrvConfig; import com.moshi.receptionist.common.exception.SessionExistException; import com.moshi.receptionist.remoting.ChannelEventListener; /** * * 墨仕服务器支撑 * <p>com.moshi.push.recepsrv.routeinfo * <p>File: SessionManager.java 创建时间:2014年7月21日下午1:29:28</p> * <p>Title: 会话管理器</p> * <p>Description: 管理各个链路的会话信息</p> * <p>Copyright: Copyright (c) 2014 墨仕</p> * <p>Company: 墨仕</p> * <p>模块: 推送服务</p> * @author 徐剑 * @version 0.0.1 * @history 修订历史(历次修订内容、修订人、修订时间等) */ public class SessionManager implements ChannelEventListener,SessionRepository { private static final Logger log = LoggerFactory.getLogger(SessionManager.class); private List<Channel> unAuthendChannel = new CopyOnWriteArrayList<Channel>(); private Map<String, Session> sessions = new ConcurrentHashMap<String, Session>(); private RecepsrvConfig recepsrvConfig; private int delayTasks = 5; private List<SessionRepositoryEventListener> sessionRepositoryEventListeners = new ArrayList<SessionRepositoryEventListener>(); public SessionManager(RecepsrvConfig recepsrvConfig) { this.recepsrvConfig = recepsrvConfig; } @Override public void onChannelConnect(String remoteAddr, Channel channel) { if(log.isDebugEnabled()){ log.debug("{} is connected!",remoteAddr); } channel.attr(Session.CONNECT_TIMESTAMP).set(System.currentTimeMillis()); unAuthendChannel.add(channel); } @Override public void onChannelClose(String remoteAddr, Channel channel) { if(log.isDebugEnabled()){ log.debug("{} is closed!",remoteAddr); } if(unAuthendChannel.remove(channel)){ return; } removeSession(channel.attr(Session.SESSION_NAME).get()); } @Override public void onChannelException(String remoteAddr, Channel channel) { if(log.isDebugEnabled()){ log.debug("{} is throw exception!",remoteAddr); } onChannelClose(remoteAddr, channel); } @Override public void onChannelIdle(String remoteAddr, Channel channel) { if(log.isDebugEnabled()){ log.debug("{} is idle!",remoteAddr); } if(unAuthendChannel.remove(channel)){ return; } String sessionName = channel.attr(Session.SESSION_NAME).get(); Session session = sessions.get(sessionName); int currentIdleTime = session.currentIdleTime(); if(currentIdleTime>recepsrvConfig.getMaxIdle()){ channel.close(); removeSession(sessionName); return; } session.idle(); } @Override public Session findSession(String sessionName) { return sessions.get(sessionName); } @Override public boolean isExist(String sessionName) { return sessions.containsKey(sessionName); } @Override public void removeSession(String sessionName) { Session session =sessions.get(sessionName); if(session!=null){ sessions.remove(sessionName); for(SessionRepositoryEventListener listener:sessionRepositoryEventListeners){ listener.onSessionRemoved(session); } } } @Override public void removeSession(Session session) { removeSession(session.getSessionName()); } @Override public Session buildUserSession(Channel channel, String sessionName, String token) throws SessionExistException { unAuthendChannel.remove(channel); if(this.sessions.containsKey(sessionName)){ Session session = findSession(sessionName); if(session!=null&&session.getChannel()==channel){ return session; } throw new SessionExistException(); } Session session = new DefaultUserSession(channel, sessionName, token); sessions.put(sessionName, session); channel.attr(Session.SESSION_NAME).set(sessionName); for(SessionRepositoryEventListener listener:sessionRepositoryEventListeners){ listener.onUserSessionBuild(session); } return session; } @Override public void registerEventListener(SessionRepositoryEventListener listener) { sessionRepositoryEventListeners.add(listener); } @Override public void unRegisterEventListener(SessionRepositoryEventListener listener) { sessionRepositoryEventListeners.remove(listener); } public int getDelayTasks() { return delayTasks; } public void setDelayTasks(int delayTasks) { this.delayTasks = delayTasks; } @Override public int countSize() { return sessions.size(); } }