Presentation is loading. Please wait.

Presentation is loading. Please wait.

Implementierung eines IRC Servers in Java

Similar presentations


Presentation on theme: "Implementierung eines IRC Servers in Java"— Presentation transcript:

1 Implementierung eines IRC Servers in Java
von M. Serhat Cinar AI WPF Compiler & Interpreter SS04 bei Prof. Dr. Ehses

2 IRC IRC := Internet Relay Chat (Relay = Relais, Übertragung)
Der Benutzer meldet sich bei einem Server (z.B. A) an. Dieser Server wiederum ist mit anderen Servern desselben Netzes verbunden (z.B. mit Server C über Server B). Jeder Benutzer, der mit einem Server verbunden ist erhält vom Server eine Liste aller Channels, die in dem jeweiligen Netz verfügbar sind und kann sich in jedem beliebigen Channel anmelden (JOIN). Das IRC-Geflecht von Servern ist in Netze aufgeteilt. Beispiele für verschiedene große Netze sind das DALnet, Efnet oder IRCnet. Benutzer im selben Channel können sich unterhalten (chatten). Schickt Benutzer A über Server A eine Nachricht an Benutzer C an Server C, so wird die Nachricht wie ein PING über das IRC-Netz geschickt. Die verschiedenen Stationen bei einer solchen Weiterleitung nennt man Relais. Das Prinzip ist dem DNS, Mail-Relay oder dem PING Protokoll ähnlich.

3 IRC als Netzwerk

4 IRC - Standard Die Standards für das IRC-Protokoll werden in den Request for Comments (RFC‘s) verwaltet. RFC IRC Protocol RFC IRC Architecture RFC IRC Channel Management RFC IRC Client Protocol RFC IRC Server Protocol

5 RFC 2812 Internet Relay Chat: Client Protocol 1/2
message = [ ":" prefix SPACE ] command [ params ] crlf prefix = servername / ( nickname [ [ "!" user ] host ] ) command = 1*letter / 3digit params = *14( SPACE middle ) [ SPACE ":" trailing ] =/ 14( SPACE middle ) [ SPACE [ ":" ] trailing ] nospcrlfcl = %x01-09 / %x0B-0C / %x0E-1F / %x21-39 / %x3B-FF ; any octet except NUL, CR, LF, " " and ":" middle = nospcrlfcl *( ":" / nospcrlfcl ) trailing = *( ":" / " " / nospcrlfcl ) SPACE = %x ; space character crlf = %x0D %x0A ; "carriage return" "linefeed" letter = %x41-5A / %x61-7A ; A-Z / a-z digit = %x ; 0-9 hexdigit = digit / "A" / "B" / "C" / "D" / "E" / "F" special = %x5B-60 / %x7B-7D ; "[", "]", "\", "`", "_", "^", "{", "|", "}„ user = 1*( %x01-09 / %x0B-0C / %x0E-1F / %x21-3F / %x41-FF ) ; any octet except NUL, CR, LF, " " and

6 RFC 2812 Internet Relay Chat: Client Protocol 2/2
key = 1*23( %x01-05 / %x07-08 / %x0C / %x0E-1F / %x21-7F ) ; any 7-bit US_ASCII character, ; except NUL, CR, LF, FF, h/v TABs, and " " servername = hostname host = hostname / hostaddr hostname = shortname *( "." shortname ) shortname = ( letter / digit ) *( letter / digit / "-" ) *( letter / digit ) ; as specified in RFC 1123 [HNAME] hostaddr = ip4addr / ip6addr ip4addr = 1*3digit "." 1*3digit "." 1*3digit "." 1*3digit ip6addr = 1*hexdigit 7( ":" 1*hexdigit ) ip6addr =/ "0:0:0:0:0:" ( "0" / "FFFF" ) ":" ip4addr nickname = ( letter / special ) *8( letter / digit / special / "-" )

7 Message Grundstruktur
:Prefix Command Paramlist Server / User SPACE Param * :Trailing

8 Verschiedene Implementierungen: CRLF vs. LF
RFC 2812: message = [ ":" prefix SPACE ] command [ params ] crlf crlf = %x0D %x0A mIRC: 4E B A NICK test. BitchX: 4E B D 0A NICK test..

9 jIrcSX.flex 1/2 CR = \x0D LF = \x0A CRLF = {CR} {LF} SPACE = \x20
DIGIT = \x30|\x31|\x32|\x33|\x34|\x35|\x36|\x37|\x38|\x39 LETTER_HEX = "A" | "B" | "C" | "D" | "E" | "F" LETTER = [A-Za-z] COLON = ":" AT = EXCLAMATION_MARK = "!" DOT = "." VALUE = "#" COMMA = "," PLUS = "+" MINUS = "-" AND = "&"

10 jIrcSX.flex 2/2 UNDERSCORE = "_" ACCENT_CIRCONFLEX = "^"
SQUARED_BRACKET_LEFT = "[" SQUARED_BRACKET_RIGHT = "]" BRACE_LEFT = "{" BRACE_RIGHT = "}" BACKSLASH = "\\" APOSTROPHE = "`" OR = "|" TAB = \x09 NULL = \x00 BELL = \x07 FF = \x0C SYMBOL_OTHER = . HEXDIGIT = {DIGIT} | {LETTER_HEX} IP6ADDR = ( {HEXDIGIT}+ (":" {HEXDIGIT}+){7} ) | ( "0:0:0:0:0:" ("0"|"FFFF") ":" {IP4ADDR} ) IP4ADDR = {DIGIT} {1,3} "." {DIGIT} {1,3} "." {DIGIT} {1,3} "." {DIGIT} {1,3} HOSTNAME = {SHORTNAME} ( "." {SHORTNAME})+ SHORTNAME = ( {LETTER} | {DIGIT} ) ( {LETTER} | {DIGIT} | "-" )* ( {LETTER} | {DIGIT} )*

11 Recursive Descending Parser
private int lookahead(), private void match(int symbol), private void match() public INode parse(String pIrcMessage) private INode message() private INode prefix() private String nickname() private String letterOrSpecial() private String letterOrSpecialOrDigitOrMinusOrEmpty() private String user() private String userLetterOrEmpty() private INode host() private INode hostaddr() private INode command() private INode params() private String middle() private String middleRepeatOrEmpty() private String trailing()

12 MessageNode public class MessageNode implements INode {
public INode mPrefix, mCommand, mParams; public void accept(IVisitor v)[...] public String getCommand(){ return ((CommandNode) mCommand).mCommand; } public boolean hasColonedTrailing(){ if (mParams==null) return false; return ((ParamsNode) mParams).mColonedTrailing; public int getParamsSize(){ if (mParams==null) return 0; return ((ParamsNode) mParams).mMiddles.size(); public String getParam(int i){ if (mParams==null) return null; ParamsNode lPN = (ParamsNode) mParams; if (lPN.mMiddles == null || lPN.mMiddles.size()<=i) return null; return ((String)lPN.mMiddles.get(i));

13 Weitere Nodes 1/2 public class PrefixHostNameNode implements INode {
public String mServerName; [...] } public class CommandNode implements INode { public String mCommand; public class PrefixNickUserHostNode implements INode { public String mNickName, mUser; public INode mHost;

14 Weitere Nodes 2/2 public class IPv4AdressNode implements INode {
public String mAdress; [...] } public class ParamsNode implements INode { public Vector mMiddles; public boolean mColonedTrailing = false;

15 Verbindungsaufbau Client->Server 1/2
The commands described here are used to register a connection with an IRC server as a user as well as to correctly disconnect. A "PASS" command is not required for a client connection to be registered, but it MUST precede the latter of the NICK/USER combination (for a user connection) or the SERVICE command (for a service connection). The RECOMMENDED order for a client to register is as follows: 1. Pass message 2. Nick message Service message 3. User message Upon success, the client will receive an RPL_WELCOME (for users) or RPL_YOURESERVICE (for services) message indicating that the connection is now registered and known the to the entire IRC network. The reply message MUST contain the full client identifier upon which it was registered.

16 Verbindungsaufbau Client->Server 2/2
NICK test USER test "" "irc.gamesnet.net" :x :genesis.GamesNET.net NOTICE AUTH :Looking up the hostname for :genesis.GamesNET.net NOTICE AUTH :Please wait while your system is scanned for insecure proxy servers... :genesis.GamesNET.net NOTICE AUTH :Successfully resolved your IP to xdsl netcologne.de. PING : E PONG : E :genesis.GamesNET.net 001 test :Welcome to the Internet Relay Chat network, = Client = Server

17 NICK Message Command: NICK Parameters: <nickname>
NICK command is used to give user a nickname or change the existing one. Numeric Replies: ERR_NONICKNAMEGIVEN ERR_ERRONEUSNICKNAME ERR_NICKNAMEINUSE ERR_NICKCOLLISION ERR_UNAVAILRESOURCE ERR_RESTRICTED Examples: NICK Wiz ; Introducing new nick "Wiz" if session is still unregistered, or user changing his nickname to "Wiz" NICK Kilroy ;Server telling that WiZ changed his nickname to Kilroy.

18 Weitere Befehle 1/3 3.1 Connection Registration 3.1.1 Password message
Nick message User message Oper message User mode message Service message Quit Squit 3.2 Channel operations Join message Part message Channel mode message Topic message Names message List message Invite message Kick command

19 Weitere Befehle 2/3 3.3 Sending messages 3.3.1 Private messages
Notice 3.4 Server queries and commands Motd message Lusers message Version message Stats message Links message Time message Connect message Trace message Admin command Info command 3.5 Service Query and Commands Servlist message Squery

20 Weitere Befehle 3/3 3.6 User based queries 3.6.1 Who query
Whois query Whowas 3.7 Miscellaneous messages Kill message Ping message Pong message Error 4. Optional features 4.1 Away 4.2 Rehash message 4.3 Die message 4.4 Restart message 4.5 Summon message 4.6 Users 4.7 Operwall message 4.8 Userhost message 4.9 Ison message

21 RegistrationProcessor
Software Architektur . UserList 1 1 1 * Server 1 * ClientHandler 1 1 User 1 1 1 1 1 44.. RDParser RegistrationProcessor CommandProcessor

22 User Die Klasse User verwaltet userbezogene Informationen.
public class User { public String mNick; public ClientHandler mClientHandler; public String mPass; public String mUsername; public String mHostname; public String mRealname; public String mMode; public MessageNode mLastMessage; public String mInternetAdress; }

23 Server Der Server erzeugt einen ServerSocket auf dem IRC Port Für jede ankommende Verbindung wird ein eigener ClientHandler erzeugt. while (mRunning){ new ClientHandler(lServerSocket.accept(), this); } Weiterhin stellt der Server Zentrale Informationen zur Verfügung, wie die Liste der aktuell verbundenen Clients. public String getName() public String getServerAdress() public String getServerAdressString() public int getServerPort() public UserList getUserList()

24 ClientHandler 1/3 Jeder Client erhält einen eigenen ClientHandler, der als nebenläufiger Prozess alle Eingabezeichen des Clients aus dem InputStream des Sockets liest, bis das Ende einer Message erreicht wird und anschließend parst. public synchronized MessageNode getNextMessageNode() throws SyntaxException, IOException{ StringBuffer lInputBuffer = new StringBuffer(); int lReadByte; while ( (lReadByte = mInputReader.read()) != -1){ lInputBuffer.append((char)lReadByte); if (lInputBuffer.indexOf(LexicalSymbols.STRING_LF)>-1) break; } if (lReadByte==-1) mUser.mLastMessage = null; else mUser.mLastMessage = (MessageNode) mServer.parse(lInputBuffer.toString()); return mUser.mLastMessage;

25 ClientHandler 2/3 Weitere Methoden ermöglichen das Senden von Nachrichten über den OutputSteam: public synchronized void sendMessage(String pMessage){ Log.getInstance().writeln(toString()+" sending: "+pMessage); mPrintWriter.print(pMessage+LexicalSymbols.STRING_CRLF); mPrintWriter.flush(); } public synchronized void sendNumericReply(String [] pNumber){ sendMessage(NumericReplies.getNumericReplyMessage(pNumber, mUser));

26 ClientHandler 3/3 try { RegistrationProcessor lRegistration = new RegistrationProcessor(); lRegistration.process(mUser, null); while (mRunning){ // read next message from client lMessage = getNextMessageNode(); if (lMessage==null)mRunning = false; if (mCommandProcessors.containsKey(lMessage.getCommand().toUpperCase())){ lCommandProcessor = (ICommandProcessor) mCommandProcessors.get(lMessage.getCommand().toUpperCase()); lCommandProcessor.process(mUser, lMessage); } catch (SyntaxException e) { Log.getInstance().writeln("ParseException: "+e.toString()); sendNumericReply(NumericReplies.ERR_NEEDMOREPARAMS);

27 ICommandProcessor public interface ICommandProcessor {
public void process(User pUser, MessageNode pMessageNode) throws IOException; public String getCommandString(); }

28 NickProcessor public void process(User pUser, MessageNode pMessageNode) throws IOException { String lNewNick = pMessageNode.getParam(0); if (lNewNick != null){ UserList lList = pUser.mClientHandler.getServer().getUserList(); lList.renameUser(pUser, lNewNick); // TODO broadcast new nick of user } else pUser.mClientHandler. sendNumericReply( NumericReplies.ERR_NONICKNAMEGIVEN); public String getCommandString() { return CommandStrings.NICK;

29 PingProcessor public void process(User pUser, MessageNode pMessageNode) throws IOException { // PING : E // PONG : E String lPingCode = pMessageNode.getParam(0); if (lPingCode != null) pUser.mClientHandler.sendMessage("PONG :"+lPingCode); else pUser.mClientHandler.sendMessage("PONG"); } public String getCommandString() { return CommandStrings.PING;

30 Auszug einer Login-Prozedur 1/2
Client connected: ClientHandler received: "NICK test" COMMAND: NICK MIDDLE: test ClientHandler test received: "USER test "" " " :x" COMMAND: USER MIDDLE: "" MIDDLE: " " ClientHandler test sending: : test :Welcome to the Internet Relay Network ClientHandler test sending: : test :Your host is [ :6667], running version jIRC Server X Version ClientHandler test sending: : test :This server was created <date>

31 Auszug einer Login-Prozedur 2/2
ClientHandler test sending: : test : [ :6667] <version> <available user modes> <available channel modes> ClientHandler test sending: : test :Try server , port <port number> ClientHandler test sending: : test :There are <integer> users and <integer> services on <integer> servers ClientHandler test sending: : test <integer> :operator(s) online ClientHandler test sending: : test <integer> :unknown connection(s) ClientHandler test sending: : test <integer> :channels formed ClientHandler test sending: : test :I have <integer> clients and <integer> servers ClientHandler test sending: : test :- <server> Message of the day - ClientHandler test sending: : test :- <text> ClientHandler test sending: : test :End of MOTD command

32 TODO Weitere IRC Befehle über die Schnittstelle ICommandProcessor implementieren Channel Verwaltung Server to Server Kommunikation

33 Referenzen jIrcSX – www.graviton.de/ai/c-und-i
Der in diesem Projekt entstehende IRC-Server BitchX – DOS IRC Client für Unix/Linux/MacOS/Windows mIRC - IRC Client mit GUI für Windows RFC Archiv - jFlex – jflex.de Java Scanner Generator


Download ppt "Implementierung eines IRC Servers in Java"

Similar presentations


Ads by Google