home *** CD-ROM | disk | FTP | other *** search
Java Source | 1996-08-14 | 15.8 KB | 676 lines |
- import java.io.*;
- import java.net.*;
- import java.util.*;
-
- public class IRCd {
- public static void main( String argv[] ) {
- int port = 6667;
- if( argv.length == 1 )
- {
- try {
- port = new Integer( argv[0] ).intValue();
- } catch( NumberFormatException n ) {
- port = 6667;
- }
- }
- System.out.println( "Staring IRCd on port: "+port );
- IRCDaemon daemon = new IRCDaemon( port );
- }
- }
-
- class IRCDaemon {
- ServerSocket server;
- Vector channels;
- Vector users;
- int port = 6667;
-
- public IRCDaemon( int port ) {
- try {
- this.port = port;
- waitForConnections();
- } catch( IOException e ) {
- try {
- if( server != null ) server.close();
- } catch( Exception ex ) {}
- }
- }
-
- public void waitForConnections() throws IOException {
- channels = new Vector();
- users = new Vector();
-
- server = new ServerSocket( port );
-
- while( true )
- {
- Socket socket = server.accept();
- IRCThread thread = new IRCThread( socket, this );
- thread.start();
- }
- }
-
- synchronized void addUser( User user ) {
- users.addElement( user );
- }
-
- synchronized void removeUser( User user ) {
- users.removeElement( user );
- }
-
- synchronized Vector getUsers() {
- return users;
- }
-
-
- synchronized User getUserByName( String name ) {
- Enumeration e = users.elements();
-
- while( e.hasMoreElements() ) {
- User user = (User)e.nextElement();
-
- if( user.getNickName() != null )
- {
- if( user.getNickName().equals( name ) )
- return user;
- }
- }
-
- return null;
- }
-
- synchronized boolean isNickNamePossibleIfYesTakeIt( String name, User ego ) {
- Enumeration e = users.elements();
-
- while( e.hasMoreElements() ) {
- User user = (User)e.nextElement();
-
- if( user.getNickName() != null )
- if( user.getNickName().equals( name ) )
- return false;
- }
-
- ego.setNickName( name );
- return true;
- }
-
- synchronized Vector getChannels() {
- return channels;
- }
-
- synchronized void partChannelNoMessage( User user, Channel ch ) throws IOException {
- ch.removeUser( user );
- user.setChannel( null );
-
- if( ch.getUsers().isEmpty() )
- channels.removeElement( ch );
- }
-
- synchronized void partChannel( User user, Channel ch ) throws IOException {
- ch.sendToAll( ":"+user.getNickName()+"!email@foo.bar PART "+ch.getChannelName()+"\n" );
-
- partChannelNoMessage( user, ch );
- }
-
- synchronized Channel getChannelByName( String chname ) {
- Enumeration e = channels.elements();
-
- while( e.hasMoreElements() ) {
- Channel ch = (Channel)e.nextElement();
-
- if( ch.getChannelName().equals( chname ) )
- {
- return ch;
- }
- }
-
- return null;
- }
-
- synchronized Channel joinChannel( User user, String chname ) throws IOException {
- Channel ch = getChannelByName( chname );
-
- if( ch != null )
- {
- joinChannel( user, ch );
- return ch;
- }
-
- // no channel found -> create a new one
-
- ch = new Channel( chname );
- channels.addElement( ch );
-
- joinChannel( user, ch );
- return ch;
- }
-
- synchronized Channel joinChannel( User user, Channel ch ) throws IOException {
- user.setChannel( ch );
- ch.addUser( user );
-
- ch.sendToAll( ":"+user.getNickName()+"!email@foo.bar JOIN :"+ch.getChannelName()+"\n" );
- user.send( ":faui42 353 "+user.getNickName()+" = "+ch.getChannelName()+" : don't care\n" );
- user.send( ":faui42 366 "+user.getNickName()+" "+ch.getChannelName()+" :End of /NAMES.\n" );
- return ch;
- }
- }
-
- class IRCThread extends Thread {
- DataInputStream input = null;
- DataOutputStream output = null;
- Socket socket = null;
- IRCDaemon ircd = null;
- User ego = null;
-
- public IRCThread( Socket socket, IRCDaemon ircd ) {
- this.socket = socket;
- this.ircd = ircd;
- }
-
- public void run() {
- try {
- input = new DataInputStream( socket.getInputStream() );
- output = new DataOutputStream( socket.getOutputStream() );
-
- waitForInput();
- } catch( IOException e ) {
- Log.log( "Line to '"+ego+"' dropped :"+e.toString() );
-
- try {
- if( socket != null )
- {
- socket.close();
- input.close();
- output.close();
- }
-
- if( ego != null ) {
- // oh, this here is diffcult, because the line dropped already
- // ego.getChannel().sendToAll( ":"+ego.getNickName()+"!email@foo.bar QUIT "+ego.getChannel().getChannelName()+"\n" );
- ircd.removeUser( ego );
-
- if( ego.getChannel() != null )
- {
- ego.setDataOutputStream( null );
- ego.setSocket( null );
- ircd.partChannel( ego, ego.channel );
- // well to be honest this is a quit, but
- // it doesn't matter
- }
- }
-
- } catch( Exception ex ) {
- Log.log( "Exception while logging out: "+ex.toString() );
- ex.printStackTrace();
- }
- }
- }
-
- static final int CMD_ERROR = -1;
- static final int CMD_USER = 0;
- static final int CMD_NICK = 1;
- static final int CMD_PRIVMSG = 2;
- static final int CMD_QUIT = 3;
- static final int CMD_JOIN = 4;
- static final int CMD_PART = 5;
- static final int CMD_LIST = 6;
- static final int CMD_WHO = 7;
- static final int CMD_TOPIC = 8;
- static final int CMD_KICKUSER = 9;
-
- void waitForInput() throws IOException {
- String line;
- boolean running;
- int cmd;
- CallObject command = new CallObject();
- CallObject ret1 = new CallObject();
- CallObject ret2 = new CallObject();
- CallObject ret3 = new CallObject();
- CallObject ret4 = new CallObject();
-
-
- running = true;
- while( running )
- {
- line = input.readLine();
- if( line == null ) throw new IOException();
-
- Log.log( line );
- parseLine( line, command, ret1, ret2, ret3, ret4 );
-
- cmd = ((Integer)command.get()).intValue();
-
- switch( cmd )
- {
- case CMD_USER:
- ego = new User( (String)ret4.get(), output, socket );
- ircd.addUser( ego );
- break;
-
- case CMD_NICK:
- if( ego == null ) break;
-
- String newnick = (String)ret1.get();
- String oldnick = ego.getNickName();
-
- if( ircd.isNickNamePossibleIfYesTakeIt( newnick, ego ) )
- {
- if( oldnick == null ) // logged in now!
- {
- // now send the login message!
-
- output.writeBytes( ":faui42 001 "+newnick+" :Welcome to COMO\n" );
- output.writeBytes( ":faui42 002 "+newnick+" :Your host is foo.bar\n" );
- output.writeBytes( ":faui42 003 "+newnick+" :(c) 1996 Jan Kautz\n" );
- output.writeBytes( ":faui42 004 "+newnick+" :COMO-IRC-Client 1.0\n" );
- output.writeBytes( ":faui42 251 "+newnick+" :There are "+ircd.getUsers().size()+" users\n" );
- output.writeBytes( ":faui42 254 "+newnick+" "+ircd.getChannels().size()+" :channels formed\n" );
- output.writeBytes( ":faui42 375 "+newnick+" :- foo.bar MOTD\n" );
- output.writeBytes( ":faui42 372 "+newnick+" :- Como-Server\n" );
- output.writeBytes( ":faui42 372 "+newnick+" :- 96/03/20\n" );
- output.writeBytes( ":faui42 376 "+newnick+" :End of /MOTD command.\n" );
- }
-
- if( ego.getChannel() != null ) {
- ego.getChannel().sendToAll( ":"+oldnick+"!email@foo.bar NICK :"+newnick+"\n" );
- } else {
- if( oldnick != null )
- output.writeBytes( ":"+oldnick+"!email@foo.bar NICK :"+newnick+"\n" );
- }
- }
- else
- output.writeBytes( ":faui42 433 * "+newnick+" :Nickname in use\n" );
- break;
-
- case CMD_TOPIC:
- // TODO::::!!!
- if( ego == null || ego.getNickName() == null || ego.getChannel() == null ) break;
-
- String forchannel = (String)ret1.get();
- String topic = (String)ret2.get();
-
- Channel topchan = ircd.getChannelByName( forchannel );
- topchan.setTopic( topic );
- break;
-
- case CMD_KICKUSER:
- if( ego == null || ego.getNickName() == null ) break;
-
- User kickwhom = ircd.getUserByName( (String)ret1.get() );
-
- if( kickwhom != null ) {
- // attention don't kick yourself!!!
-
- // This causes a Line dropped in the corresponding
- // readthread :-)
- kickwhom.getSocket().close();
-
- /*
- ircd.removeUser( kickwhom );
-
- if( kickwhom.channel != null ) ircd.partChannel( kickwhom, kickwhom.channel );
- */
- }
- break;
-
- case CMD_PRIVMSG:
- if( ego == null || ego.getNickName() == null ) break;
-
- String towhat = (String)ret1.get();
-
- Channel tochan = ircd.getChannelByName( towhat );
- if( tochan != null ) {
- tochan.sendToAllExceptOne( ":"+ego.getNickName()+"!email@foo.bar PRIVMSG "+towhat+" :"+(String)ret2.get()+"\n", ego);
- }
- else {
- // let's look if there's a user named 'towhat'
-
- User anybody = ircd.getUserByName( towhat );
-
- if( anybody != null ) {
- // TODO: check if user is on my channel
-
- anybody.send( ":"+ego.getNickName()+"!email@foo.bar PRIVMSG "+towhat+" :"+(String)ret2.get()+"\n" );
- }
- }
- break;
-
- case CMD_JOIN:
- if( ego == null || ego.getNickName() == null ) break;
- if( ego.getChannel() != null ) ircd.partChannel( ego, ego.channel );
-
- Channel jch = ircd.joinChannel( ego, (String)ret1.get() );
- break;
-
- case CMD_PART:
- if( ego == null || ego.getNickName() == null ) break;
- if( ego.channel != null ) ircd.partChannel( ego, ego.channel );
- break;
-
- case CMD_QUIT:
- running = false;
-
- if( ego == null ) break;
-
- ircd.removeUser( ego );
-
- if( ego.channel != null ) ircd.partChannel( ego, ego.channel );
-
- running = false;
- break;
-
- case CMD_LIST:
- Enumeration elist = ircd.getChannels().elements();
-
- output.writeBytes( ":faui42 321 "+ego.getNickName()+" Channel :Users Name\n" );
- while( elist.hasMoreElements() ) {
- Channel channel = (Channel)elist.nextElement();
- output.writeBytes( ":faui42 322 "+ego.getNickName()+" "+channel.getChannelName()+" "+channel.getUsers().size()+" : "+channel.getTopic()+"\n" );
- }
- output.writeBytes( ":faui42 323 "+ego.getNickName()+" :End of /LIST\n" );
- break;
-
- case CMD_WHO:
- String whatchannel = (String)ret1.get();
-
- if( ego == null ) break;
-
- // WHO * in a channel means who is in that channel
- if( ego.getChannel() != null &&
- (whatchannel == null || whatchannel.equals( "*" ) ) )
- whatchannel = ego.getChannel().getChannelName();
-
- if( whatchannel == null || whatchannel.equals( "*" ) ) {
- Enumeration e = ircd.getUsers().elements();
-
- whatchannel = "*";
-
- while( e.hasMoreElements() ) {
- User usr = (User)e.nextElement();
- output.writeBytes( ":faui42 352 "+ego.getNickName()+" "+whatchannel+
- " loginname "+usr.getSocket().getInetAddress().getHostName()+
- " faui42 "+usr.getNickName()+" H :0 "+usr.getRealName()+"\n" );
- }
- output.writeBytes( ":faui42 315 "+ego.getNickName()+" "+whatchannel+
- " :End of /WHO list.\n" );
- }
- else {
- Channel byname = ircd.getChannelByName( whatchannel );
- if( byname != null ) {
- Enumeration e = byname.getUsers().elements();
-
- while( e.hasMoreElements() ) {
- User usr = (User)e.nextElement();
- output.writeBytes( ":faui42 352 "+ego.getNickName()+" "+whatchannel+
- " loginname "+usr.getSocket().getInetAddress().getHostName()+" faui42 "+
- usr.getNickName()+" H :0 "+usr.getRealName()+"\n" );
- }
- }
- output.writeBytes( ":faui42 315 "+ego.getNickName()+" "+whatchannel+
- " :End of /WHO list.\n" );
- }
- break;
-
- default:
- Log.log( "Unknown message :"+line );
- break;
- }
- }
-
- // now close the socket!
- socket.close();
- }
-
- void parseLine( String line, CallObject command, CallObject ret1, CallObject ret2, CallObject ret3, CallObject ret4 ) {
- StringTokenizer st = new StringTokenizer( line, " \n\r" );
- String str[] = new String[5];
- int i = 0;
- int cmd = CMD_ERROR;
-
- command.set( new Integer( cmd ) );
-
- while( st.hasMoreTokens() ) {
- str[i] = st.nextToken();
- i++;
- if( i == 5 ) break;
- }
-
- if( i == 0 ) return;
-
- if( str[0].equalsIgnoreCase( "NICK" ) ) cmd = CMD_NICK;
- else if( str[0].equalsIgnoreCase( "JOIN" ) ) cmd = CMD_JOIN;
- else if( str[0].equalsIgnoreCase( "USER" ) ) cmd = CMD_USER;
- else if( str[0].equalsIgnoreCase( "PART" ) ) cmd = CMD_PART;
- else if( str[0].equalsIgnoreCase( "QUIT" ) ) cmd = CMD_QUIT;
- else if( str[0].equalsIgnoreCase( "WHO" ) ) cmd = CMD_WHO;
- else if( str[0].equalsIgnoreCase( "LIST" ) ) cmd = CMD_LIST;
- else if( str[0].equalsIgnoreCase( "PRIVMSG" ) ) cmd = CMD_PRIVMSG;
- else if( str[0].equalsIgnoreCase( "TOPIC" ) ) cmd = CMD_TOPIC;
- else if( str[0].equalsIgnoreCase( "KICKUSER" ) ) cmd = CMD_KICKUSER;
- else return;
-
- switch( cmd ) {
- case CMD_USER:
- if( i < 5 ) return;
-
- ret1.set( str[1] );
- ret2.set( str[2] );
- ret3.set( str[3] );
- ret4.set( str[4] );
-
- int ix = line.indexOf( ':' );
- if( ix < 0 ) break;
-
- ret4.set( line.substring( ix+1 ) );
- break;
-
- case CMD_NICK:
- if( i != 2 ) return;
-
- ret1.set( str[1] );
- break;
-
- case CMD_PRIVMSG:
- ret1.set( str[1] );
- int index = line.indexOf( ':' );
- if( index < 0 ) return;
- ret2.set( line.substring( index+1 ) );
- break;
-
- case CMD_TOPIC:
- ret1.set( str[1] );
- int idx = line.indexOf( ':' );
- if( idx < 0 ) return;
- ret2.set( line.substring( idx+1 ) );
- break;
-
- case CMD_QUIT:
- if( i != 1 ) return;
-
- ret1.set( str[1] );
- break;
-
- case CMD_JOIN:
- if( i != 2 ) return;
-
- ret1.set( str[1] );
- break;
-
- case CMD_PART:
- if( i != 2 ) return;
-
- ret1.set( str[1] );
- break;
-
- case CMD_KICKUSER:
- if( i != 2 ) return;
-
- ret1.set( str[1] );
- break;
-
- case CMD_WHO:
- if( i != 1 && i != 2 ) return;
-
- ret1.set( str[1] );
- break;
-
- case CMD_LIST:
- if( i != 1 && i != 2 ) return;
-
- ret1.set( str[1] );
- break;
- }
-
- command.set( new Integer( cmd ) );
- return;
- }
- }
-
- class User {
- String realname = null;
- String nickname = null;
- Channel channel = null;
- DataOutputStream output = null;
- Socket socket = null;
-
- public User( String real, DataOutputStream output, Socket socket ) {
- realname = real;
- this.output = output;
- this.socket = socket;
- }
-
- public User( String real, String nick, DataOutputStream output ) {
- realname = real;
- nickname = nick;
- this.output = output;
- this.socket = socket;
- }
-
- public void setNickName( String name ) {
- nickname = name;
- }
-
- public String getNickName() {
- return nickname;
- }
-
-
- public String getRealName() {
- return realname;
- }
-
- public void setChannel( Channel ch ) {
- channel = ch;
- }
-
- public Channel getChannel() {
- return channel;
- }
-
- public void setDataOutputStream( DataOutputStream output ) {
- this.output = output;
- }
-
- public DataOutputStream getDataOutputStream() {
- return output;
- }
-
- public void setSocket( Socket socket ) {
- this.socket = socket;
- }
-
- public Socket getSocket() {
- return socket;
- }
-
- synchronized public void send( String str ) throws IOException {
- if( output != null )
- {
- output.writeBytes( str );
- output.flush();
- }
- }
-
- public String toString() {
- return "Nick: "+nickname+" Real: "+realname;
- }
- }
-
- class Channel {
- String name;
- Vector users;
- String topic = "none";
-
- public Channel( String name ) {
- this.name = name;
- users = new Vector();
- }
-
- public Vector getUsers() {
- return users;
- }
-
- public void addUser( User user ) {
- users.addElement( user );
- }
-
- public void removeUser( User user ) {
- users.removeElement( user );
- }
-
- public String getTopic() {
- return topic;
- }
-
- public void setTopic( String topic ) {
- this.topic = topic;
- }
-
- public String getChannelName() {
- return name;
- }
-
- public void sendToAll( String str ) {
- sendToAllExceptOne( str, null );
- }
-
- public void sendToAllExceptOne( String str, User except ) {
- Enumeration e = users.elements();
-
- while( e.hasMoreElements() ) {
- User user = (User)e.nextElement();
-
- if( user != except )
- {
- try {
- user.send( str );
- } catch( IOException exception ) {
- if( user.getSocket() != null )
- {
- // this will cause a line-drop in the read-thread
- // of that user!
- try {
- user.getSocket().close();
- } catch( Exception ekzeption ) {}
- }
- }
- }
- }
- }
-
- public String toString() {
- return "Channel: "+name + " Users: "+users;
- }
- }
-
- class Log {
- public Log() {}
-
- static void log( int val, String out ) {
- log( val+" "+out );
- }
- static void log( String out ) {
- System.out.println( out );
- }
- }
-