]> Pileus Git - ~andy/spades/blob - src/org/pileus/spades/Client.java
Add support for SASL PLAIN authentication
[~andy/spades] / src / org / pileus / spades / Client.java
1 package org.pileus.spades;
2
3 import java.io.*;
4 import java.net.*;
5
6 public class Client
7 {
8         /* Preference data */
9         public  String         server   = "irc.freenode.net";
10         public  int            port     = 6667;
11         public  String         nickname = "SpadeGuest";
12         public  String         channel  = "#rhnoise";
13         public  boolean        usesasl  = false;
14         public  String         authname = "";
15         public  String         password = "";
16         public  String         username = "user";
17         public  String         hostname = "localhost";
18
19         /* Public data */
20         public  boolean        ready    = false;
21
22         /* Connection data */
23         private Socket         socket;
24         private BufferedReader input;
25         private PrintWriter    output;
26
27         /* Private data */
28         private int            mangle;
29
30         /* Public Methods */
31         public Client()
32         {
33                 Os.debug("Client: create");
34         }
35
36         public void setServer(String server, int port)
37         {
38                 this.server = server;
39                 this.port   = port;
40         }
41
42         public void setAuth(boolean usesasl, String authname, String password)
43         {
44                 this.usesasl  = usesasl;
45                 this.authname = authname;
46                 this.password = password;
47         }
48
49         public void setUser(String nickname, String channel)
50         {
51                 this.nickname = nickname;
52                 this.channel  = channel;
53         }
54
55         public boolean connect()
56         {
57                 Os.debug("Client: connect");
58
59                 try {
60                         this.socket = new Socket(this.server, this.port);
61                         this.input  = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
62                         this.output = new PrintWriter(this.socket.getOutputStream());
63                 } catch (Exception e) {
64                         Os.debug("Client: failed to create connection: " + e);
65                         return false;
66                 }
67
68                 Os.debug("Client: connected");
69                 if (this.usesasl)
70                         this.raw("CAP REQ :sasl");
71                 this.raw("USER "+this.username+" "+this.hostname+" "+this.server+" :"+this.nickname);
72                 this.raw("NICK "+this.nickname);
73
74                 return true;
75         }
76
77         public boolean abort()
78         {
79                 Os.debug("Client: abort");
80                 try {
81                         this.socket.close();
82                         this.ready = false;
83                         return true;
84                 } catch (Exception e) {
85                         Os.debug("Client: error closing socket", e);
86                         return false;
87                 }
88         }
89
90         public void raw(String line)
91         {
92                 try {
93                         Os.debug("< " + line);
94                         this.output.println(line);
95                         this.output.flush();
96                 } catch (Exception e) {
97                         Os.debug("Client: error writing line", e);
98                 }
99         }
100
101         public Message send(String txt)
102         {
103                 Message msg  = new Message(this.channel, this.nickname, txt);
104                 this.raw(msg.line);
105                 return msg;
106         }
107
108         public Message recv()
109         {
110                 try {
111                         String line = input.readLine();
112                         if (line == null)
113                                 return null;
114                         Os.debug("> " + line);
115                         Message msg = new Message(line);
116                         this.process(msg);
117                         if (this.usesasl)
118                                 this.dosasl(msg);
119                         return msg;
120                 } catch (SocketException e) {
121                         this.ready = false;
122                         return null;
123                 } catch (Exception e) {
124                         this.ready = false;
125                         Os.debug("Client: error in recv", e);
126                         return null;
127                 }
128         }
129
130         /* Private methods */
131         private void process(Message msg)
132         {
133                 if (msg.cmd.equals("001") && msg.msg.matches("Welcome.*")) {
134                         this.raw("JOIN "  + this.channel);
135                         this.raw("TOPIC " + this.channel);
136                         this.ready = true;
137                 }
138                 if (msg.cmd.equals("433")) {
139                         this.raw("NICK "+this.nickname+this.mangle);
140                         this.mangle++;
141                 }
142                 if (msg.cmd.equals("PING")) {
143                         this.raw("PING " + msg.msg);
144                 }
145         }
146
147         private void dosasl(Message msg)
148         {
149                 switch (msg.type) {
150                         case CAP:
151                                 if (msg.msg.equals("sasl") && msg.arg.equals("ACK")) {
152                                         Os.debug("Client: sasl - starting auth");
153                                         this.raw("AUTHENTICATE PLAIN");
154                                 } else {
155                                         Os.debug("Client: sasl - Server does not support sasl");
156                                 }
157                                 break;
158                         case AUTH:
159                                 if (msg.arg.equals("+")) {
160                                         Os.debug("Client: sasl - performin authentication");
161                                         this.raw("AUTHENTICATE " + Os.base64(
162                                                                 this.authname + "\0" +
163                                                                 this.authname + "\0" +
164                                                                 this.password));
165                                 } else {
166                                         Os.debug("Client: sasl - unexpected authenticate response");
167                                 }
168                                 break;
169                         case AUTHOK:
170                                 Os.debug("Client: SASL Auth Successful");
171                                 this.raw("CAP END");
172                                 break;
173                         case AUTHFAIL:
174                                 Os.debug("Client: SASL Auth Failed");
175                                 this.raw("CAP END");
176                                 break;
177                 }
178         }
179 }