Java: Began work on hub listeners.
[doldaconnect.git] / lib / java / dolda / dolcon / Session.java
CommitLineData
7131093c
FT
1package dolda.dolcon;
2
3import java.util.*;
4import dolda.dolcon.protocol.*;
5
e90ca845 6public class Session implements NotifyListener {
7131093c 7 private Connection conn;
e90ca845
FT
8 private String state;
9 private Set<HubListener> hubls = new HashSet<HubListener>();
10 private boolean listening = false;
11 private String[] hubstate = {"none"};
12 private String[][] states = {hubstate};
13 private Map<Integer, Hub> hubs = new TreeMap<Integer, Hub>();
7131093c
FT
14
15 public Session(String aspec, String username, List<Authenticator> auth) throws AuthException, ProtocolException, InterruptedException {
e90ca845 16 state = "connecting";
7131093c
FT
17 conn = new Connection(aspec);
18 conn.expectVersion(2);
19 try {
20 conn.syncConnect();
21 } catch(ConnectException e) {
22 throw(new ProtocolException(e));
23 }
e90ca845 24 state = "auth";
7131093c 25 authenticate(username, auth);
e90ca845 26 state = "";
7131093c
FT
27 }
28
29 public Session(String aspec, String username, Authenticator... auth) throws AuthException, ProtocolException, InterruptedException {
30 this(aspec, username, Arrays.asList(auth));
31 }
32
33 private void authenticate(String username, List<Authenticator> auth) throws AuthException, ProtocolException, InterruptedException {
34 Response resp;
35
36 try {
37 resp = ResponseException.check(conn.ecmd("lsauth"), 200);
38 List<String> mechs = new LinkedList<String>();
39 for(List<String> mech : resp.lines)
40 mechs.add(mech.get(0).intern());
41 String use = null;
42 Authenticator au = null;
43 for(Authenticator a : auth) {
44 System.out.println(a);
45 use = a.handles(mechs);
46 if(use != null) {
47 au = a;
48 break;
49 }
50 }
51 if(use == null)
52 throw(new NoMechException());
53 resp = conn.ecmd("login", use, username);
54 while(true) {
55 if(resp.code == 200) {
56 return;
57 } else if((resp.code / 100) == 3) {
58 resp = conn.ecmd(au.step(resp));
59 } else if((resp.code / 100) == 5) {
60 throw(new AuthException(resp.token(0, 0)));
61 } else {
62 throw(new ResponseException(resp, 0));
63 }
64 }
65 } catch(ClosedException e) {
66 throw(new ProtocolException(e));
67 }
68 }
92719bd6 69
e90ca845
FT
70 private void checkstates() {
71 boolean active = false;
72 for(String[] sp : states) {
73 if(sp[0] != "none") {
74 active = true;
75 break;
76 }
77 }
78 if(listening && !active)
79 conn.removeNotifyListener(this);
80 else if(!listening && active)
81 conn.addNotifyListener(this);
82 }
83
84 private int atoi(String a) {
85 return(Integer.parseInt(a));
86 }
87
88 private void fetchhubs() {
89 synchronized(hubstate) {
90 if(hubstate[0] != "none")
91 return;
92 hubstate[0] = "fetch";
93 }
94 Command cmd = new Command("lsnodes");
95 cmd.new Listener() {
96 public void done(Response r) {
97 if(r.code != 200)
98 return;
99 for(List<String> line : r.lines) {
100 Hub h = new Hub(atoi(line.get(0)));
101 h.fnet = line.get(1).intern();
102 h.name = line.get(2);
103 h.numpeers = atoi(line.get(3));
104 h.state = new String[] {"syn", "hs", "est", "dead"}[atoi(line.get(4))];
105 h.gid = line.get(5);
106 hubs.put(h.id, h);
107 }
108 }
109
110 public void error(Exception e) {
111 }
112 };
113 conn.qcmd(new Command("notify fn:act on"), cmd);
114 }
115
116 public void addHubListener(HubListener hl, boolean addexisting) {
117 fetchhubs();
118 synchronized(hubls) {
119 hubls.add(hl);
120 }
121 }
122
123 public void removeHubListener(HubListener hl) {
124 synchronized(hubls) {
125 hubls.remove(hl);
126 if(hubls.isEmpty()) {
127 hubs.clear();
128 hubstate[0] = "none";
129 checkstates();
130 }
131 }
132 }
133
134 public void notified(Response resp) {
135 }
136
92719bd6
FT
137 public void close() {
138 conn.close();
e90ca845
FT
139 state = "closed";
140 }
141
142 protected void finalize() {
143 if(state != "closed")
144 close();
92719bd6 145 }
7131093c 146}