⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chatserver.java

📁 piweurrrrq i o fhsadhfka fd dskajc zxkjcnkjsahc
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 2000 Lyrisoft Solutions, Inc. * Used by permission */package com.lyrisoft.chat.server.remote;import java.util.Collection;import java.util.Date;import java.util.Map;import java.util.HashMap;import java.util.Iterator;import java.util.ArrayList;import java.util.Properties;import java.util.StringTokenizer;import java.util.Vector;import java.util.HashSet;import java.net.ServerSocket;import java.net.Socket;import java.io.IOException;import java.io.BufferedReader;import java.io.InputStreamReader;import com.lyrisoft.chat.Translator;import com.lyrisoft.chat.ICommands;import com.lyrisoft.chat.Constants;import com.lyrisoft.chat.server.remote.IAuthenticator;import com.lyrisoft.util.io.*;import com.lyrisoft.util.properties.*;import com.lyrisoft.util.CircularQueue;import com.lyrisoft.chat.server.remote.command.*;import javax.jms.*;/** * This is the Chat Server */public class ChatServer implements ICommands, IServerCommands {    public static final boolean DEBUG = getDebug();    protected static Logger logger;    protected static Logger errorLogger;    protected int _port;    protected ServerSocket _serverSocket;    protected boolean _keepGoing = true;    protected long _creationTime;    protected IAuthenticator _authenticator;    protected HashMap _users;    protected HashMap _rooms;    protected String _motd;    protected Vulture _vulture;    protected Thread  _vultureThread;    protected Dispatcher _dispatcher;    protected Thread _dispatchThread;    protected Distributor _distributor;    protected Thread _distributorThread;    protected DistributedState _distributedState = new DistributedState(this);    protected int _cumulativeLogins = 0;    public ChatServer(String conf) throws Exception {        _dispatcher = createDispatcher();        _dispatchThread = new Thread(_dispatcher, "Dispatcher");        _dispatchThread.start();        System.err.println("using " + conf);        Properties p = PropertyTool.loadProperties(conf);        preProcessProperties(p);        String logFile = null;        String errorLogFile = null;        logFile = p.getProperty("log.file");        errorLogFile = p.getProperty("error.log.file");        createLoggers(logFile, errorLogFile);                String authClass = PropertyTool.getString("auth.class", p);                String commands = PropertyTool.getString("commands", p);        Properties commandProps = PropertyTool.loadProperties(commands);        initCommandProcessor(commandProps);                String messages = PropertyTool.getString("messages", p);        Properties messagesProps = PropertyTool.loadProperties(messages);        initTranslator(messagesProps);        _port = PropertyTool.getInteger("listen.port", p);        _authenticator = (IAuthenticator)Class.forName(authClass).newInstance();        String sIdle = p.getProperty("idle.timeout");        double idleTimeout = 60.0;        if (sIdle != null) {            idleTimeout = Double.valueOf(sIdle).doubleValue();        }        _vulture = new Vulture(this, idleTimeout);        readMotd();        _creationTime = System.currentTimeMillis();        _users = new HashMap();        _rooms = new HashMap();        if (System.getProperty("BSD_HACK") != null) {            log("FreeBSD Workaround is enabled.");        }                boolean useJms = false;        try {            useJms = PropertyTool.getBoolean("jms.enabled", p);        }        catch (PropertyException e) {}        if (useJms) {            _distributor = new Distributor(this, p);            _distributorThread = new Thread(_distributor, "Distributor");            _distributorThread.start();        } else {            log("Not distributing messages over JMS");        }        _serverSocket = new ServerSocket(_port);        _vultureThread = new Thread(_vulture, "Vulture");        _vultureThread.start();    }    /**     * A hook for reading in your own extra nfc.conf properties     */    public void preProcessProperties(Properties p) throws PropertyException {    }        public int getCumulativeLogins() {        return _cumulativeLogins;    }    public ChatServer() throws Exception {        this("nfc.conf");    }    protected Dispatcher createDispatcher() {        return new Dispatcher();    }    public Dispatcher getDispatcher() {        return _dispatcher;    }    public void initTranslator(Properties p) {        Translator.init(p);    }    public void initCommandProcessor(Properties p) {        CommandProcessorRemote.init(p);    }    void distributorDisconnected(Distributor d) {    }    void distributorConnected(Distributor d) {        announcePresence();    }    protected void readMotd() throws ResourceException, IOException {        BufferedReader reader = null;        StringBuffer sb = new StringBuffer();        try {            reader = new BufferedReader(new InputStreamReader(ResourceLoader.getResource("nfc.motd")));            String next;            while ((next = reader.readLine()) != null) {                sb.append(next);                sb.append("\n");            }            _motd = sb.toString();        }        finally {            if (reader != null) {                reader.close();            }        }    }    /**     * Log a message (goes to the standard log)     */    public static void log(String message) {        logger.log(message);    }    /**     * Log an error (goes to the error log)     */    public static void logError(String message) {        errorLogger.log(message);    }    /**     * Log an exception (goes to the error log)     */    public static void log(Exception e) {        errorLogger.log(e);    }    /**     * Get the RoomServer for a particular room    */    public RoomServer getRoom(String roomName) {        return (RoomServer)_rooms.get(roomKey(roomName));    }    /**     * Get a ChatClient by name     */    public ChatClient getClient(String clientName) {        return (ChatClient)_users.get(clientKey(clientName));    }    /**     * Determines if a user id is valid.  Ensures that the name is made up of     * alphanumerical characters and contains no spaces.     */    protected void validateUserId(String user) throws AccessException {        if (getName().toLowerCase().equals(user.toLowerCase())) {            throw new AccessException(Translator.getMessage("reserved_name", getName()));        } else if (Constants.SERVER_NAME.equalsIgnoreCase(user)) {            throw new AccessException(Translator.getMessage("reserved_name", Constants.SERVER_NAME));        }        char[] chars = user.toLowerCase().toCharArray();        for (int i=0; i < chars.length; i++) {            if (!Character.isLetterOrDigit(chars[i]) && chars[i] != '_' && chars[i] != '-') {                throw new AccessException(INVALID_CHARACTER);            }        }    }    public Map getUsers() {        return _users;    }    public void serverSignOn(String server) {        _distributedState.addServer(server);    }    public void serverSignOff(String server) {        _distributedState.deleteServer(server);    }    public void setRemoteUserList(String server, String[] users) {        Collection oldUsers = _distributedState.getUsersOnServer(server);        HashMap newMap = new HashMap();        // copy the ORIGINAL user list for this server into a map        for (Iterator i = oldUsers.iterator(); i.hasNext(); ) {            String s = (String)i.next();            newMap.put(clientKey(s), s);        }                // go through the NEW user list.  call remoteSignOn for each        // new user, and remove any already-known users from        // the map        for (int i=0; i < users.length; i++) {            String key = clientKey(users[i]);            if (newMap.get(key) == null) {                // user is brand new.  call remoteSignOn                remoteSignOn(server, users[i]);            } else {                // user is already known.  do nothing                newMap.remove(key);            }        }                // now the map contains users which no longer exist, so we remove them        // -- TL: I'm not sure if the map will ever have anything left in it,        // but this doesn't hurt.        for (Iterator i = oldUsers.iterator(); i.hasNext(); ) {            remoteSignOff(server, (String)i.next());        }    }    public void remoteSignOn(String server, String userId) {        // XXX check if user exists locally first, and if so we must notify        _distributedState.signon(server, userId);    }    public void remoteSignOff(String server, String userId) {        synchronized (_rooms) {            for (Iterator i = _rooms.values().iterator(); i.hasNext(); ) {                RoomServer room = (RoomServer)i.next();                if (_distributedState.userExistsInRoom(userId, room.getName())) {                    remotePartRoom(server, userId, room.getName(), true);                }            }        }        Collection deadRooms = _distributedState.signoff(server, userId);    }    /**     * Sign on to the server     * @param client the ChatClient     * @param password     * @exception AccessException is the login failed     */    public void signOn(ChatClient client, String password) throws AccessException, AccessDenied {        log(client.getUserId() + " is attempting a signon");        String userId = client.getUserId();        validateUserId(userId);        Auth auth = _authenticator.authenticate(userId, password);        client.setUserId(auth.getUserId());        synchronized (_users) {            if (_distributedState.userExists(clientKey(client))) {                throw new AccessException(ALREADY_SIGNED_ON);            } else {                int access = auth.getAccess();                client.setAccessLevel(access);                _users.put(clientKey(client), client);                log(client.getUserId() + " is authenticated.  Access = " + access +                     (client.getTunneling() ? " (tunneling)" : ""));                _cumulativeLogins++;            }        }        client.ackSignon(auth.getUserId());        sendMotd(client);                _distributedState.signon(getName(), userId);        /*        broadcastSignOnToUsers(userId); */    }    void broadcastSignOnToUsers(String userId) {        synchronized (_users) {            for (Iterator i = _users.values().iterator(); i.hasNext(); ) {                ChatClient cc = (ChatClient)i.next();                if (!cc.getUserId().equals(cc)) {                    cc.userSignOn(userId);                }            }        }    }    void broadcastSignOffToUsers(String userId) {        synchronized (_users) {            for (Iterator i = _users.values().iterator(); i.hasNext(); ) {                ChatClient cc = (ChatClient)i.next();                cc.userSignOff(userId);            }        }    }    public void broadcast(String s) {        synchronized (_users) {            for (Iterator i = _users.values().iterator(); i.hasNext(); ) {                ChatClient client = (ChatClient)i.next();                client.sendRaw(s);            }        }    }    protected void sendMotd(ChatClient client) {        StringTokenizer st = new StringTokenizer(_motd, "\r\n");        while (st.hasMoreTokens()) {            client.generalMessage(st.nextToken());        }    }    /**     * Kick a user off the system.     */    public void kill(String victim, ChatClient killer, String message) {        ChatClient c = getClient(victim);        if (c == null) {            killer.error(NO_SUCH_USER, victim);        } else {            if (c.getAccessLevel() >= killer.getAccessLevel()) {                killer.error(ACCESS_DENIED, KILL + " " + victim);            } else {                c.killed(killer.getUserId(), message);                signOff(c);                killer.ackKill(victim);            }        }    }    /**     * Sign off of the system.  This is called by the ChatClient when the socket unexpectedly     * closes, or when the user quits.     */    public void signOff(ChatClient client) {        if (client.getAccessLevel() == IAuthenticator.NONE) {            // not authenticated means not logged in.            // just kill the client and return            log("signoff: anonymous user");            client.die();            _vulture.removeClient(client);            return;        }        String name = client.getUserId();        log("signoff: " + name);                    Object o = null;        synchronized (_users) {            o = _users.remove(clientKey(client));        }        _vulture.removeClient(client);        if (o != null) {            // inform all the rooms that this user is gone            synchronized (_rooms) {                for (Iterator i = _rooms.values().iterator(); i.hasNext(); ) {                    RoomServer room = (RoomServer)i.next();                    room.part(name, true);                    if (room.isEmpty()) {                        log("Removing empty room: " + room.getName());                        i.remove();                    }                }            }        }        client.die();        Collection deadRooms = _distributedState.signoff(getName(), client.getUserId());        // notify the rest of the world (because the SignOff command processor is not        // guaranteed to execute.. For instance, if the user crashed without signing out)        distribute(client, SIGNOFF);    }    /**     * Remote a user from a room     */    public void partRoom(ChatClient client, String roomName) {        String key = roomKey(roomName);        boolean empty = false;        synchronized (_rooms) {            RoomServer room = (RoomServer)_rooms.get(key);            if (room != null) {                room.part(client, false);                if (room.isEmpty()) {                    empty = true;                    log("Removing empty room: " + roomName);                    _rooms.remove(roomKey(room));                    room = null;                }            }        }        _distributedState.part(getName(), roomName, client.getUserId());    }        public void notifyClientsRoomDestroyed(String roomName) {        synchronized (_users) {            for (Iterator i = _users.values().iterator(); i.hasNext(); ) {                ChatClient cc = (ChatClient)i.next();                cc.roomDestroyed(roomName);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -