1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package zeus.actors;
29
30 import java.net.*;
31 import java.io.*;
32 import java.util.*;
33 import zeus.util.*;
34 import zeus.concepts.*;
35
36
37 /***
38 * This component is part of the {@link MailBox}, and is responsible for
39 * reading incoming messages. This component operates within its own thread
40 * enabling the MailBox to send and receive multiple messages simultaneously. <p>
41 *
42 * It is unlikely that developers will need to call these methods directly.
43 * Although if the user wants to replace the default TCP/IP messaging mechanism
44 * this could be cleanly achieved by reimplementing the methods of this class.
45 */
46
47 public class Server extends Thread implements InTray {
48 public static final int MAX_CONNECTIONS = 1;
49 public static final int MAX_QUEUE_LENGTH = 100;
50 public static final int DEFAULT_PORT_MIN = 6700;
51 public static final int DEFAULT_PORT_MAX = 7800;
52
53 protected ServerSocket listenSocket;
54 protected Address address;
55 protected int connection_count = 0;
56 protected boolean processing;
57 private AgentContext context = null;
58
59 /***
60 timeout was originally private, but subclasses need to
61 use it to construct there own treads of control, so I changed it to protected
62 (ST -14/8/00)
63 */
64 protected long timeout = -1;
65
66 /*** Data structure holding messages as they are read in */
67 protected Queue inMail;
68
69 /*** Reference to MailBox of which this is a sub-component */
70 protected MailBox mbox;
71
72 protected MsgHandler msgHandler = null;
73
74
75
76
77
78 public Server() { ; }
79
80
81
82 public Server(AgentContext context, MailBox mbox, Queue inMail) {
83 Assert.notNull(context);
84 this.context = context;
85
86 try {
87 InetAddress ip = InetAddress.getLocalHost();
88 String localhost = ip.getHostAddress();
89 Core.DEBUG(4,"Ip Address is: " + ip);
90
91
92 boolean port_found = false;
93 for(int port = DEFAULT_PORT_MIN;
94 !port_found && port < DEFAULT_PORT_MAX; port++ ) {
95 try {
96 listenSocket = new ServerSocket(port,MAX_QUEUE_LENGTH);
97 port_found = true;
98 address = new ZeusAddress(context.whoami(),localhost,
99 port,context.whatami());
100 context.AddressBook().add(address);
101 }
102 catch (IOException e) {
103
104 }
105 }
106 if ( !port_found ) {
107 System.err.println("Cannot get a port for listening");
108
109 }
110 }
111 catch (UnknownHostException e) {
112 System.err.println("Cannot get local host IP address");
113
114 }
115 catch (IOException e) {
116 System.err.println("Cannot get a port for listening");
117 e.printStackTrace();
118
119 }
120
121
122
123 this.mbox = mbox;
124
125
126
127
128
129 this.setName("Normal server");
130 this.start();
131 }
132
133 public AgentContext getAgentContext() {
134 return mbox.getAgentContext();
135 }
136
137
138 public synchronized void updateCount(int x) {
139 debug("update count");
140 connection_count += x;
141 if ( x < 0 ) {
142 debug("notifying");
143 notify();
144 }
145 }
146
147 public void stopProcessing() {
148 processing = false;
149 }
150
151 public void lowerStatus() {
152 this.setPriority(Thread.NORM_PRIORITY-2);
153 timeout = 1000;
154 }
155
156
157 public void normalStatus() {
158 this.setPriority(Thread.NORM_PRIORITY);
159 timeout = 1000;
160 }
161
162
163
164
165
166
167
168 public void run() {
169 processing = true;
170 while(processing) {
171 debug("alive");
172 try {
173 Socket client = null;
174 client = listenSocket.accept();
175 new Connection(client, this,context.GenSym().newId());
176 yield();
177 }
178 catch (Exception e) {
179 e.printStackTrace();
180 Core.DEBUG(3,"Exception listening for connections: " + e);
181 }
182 catch (Error er ) {
183 er.printStackTrace();
184 }
185 catch (Throwable tr) {
186 tr.printStackTrace();
187 }
188
189 }
190 }
191
192
193 protected void finalize() {
194 try {
195 if ( listenSocket != null ) listenSocket.close();
196 }
197 catch(IOException e) {
198 }
199 }
200
201
202 public Address getAddress() {
203 return address;
204 }
205
206
207 /***
208 ensures that messages are processed
209 // synchronized
210 */
211 public void newMsg( Performative msg ) {
212 Address addr;
213 Time time;
214 AgentContext context = this.getAgentContext();
215 debug("1");
216 if ( (time = context.currentTime()) != null )
217 msg.setReceiveTime(time);
218
219 debug("2");
220 if ( (addr = msg.getAddress()) != null )
221 if (!addr.getType().equalsIgnoreCase("FORWARD"))
222 context.AddressBook().add(addr);
223
224
225 debug("3");
226 if (msgHandler==null)
227 msgHandler = context.getMsgHandler();
228
229
230
231 Core.DEBUG(3,"putting message from " + msg.getSender() + " on handler queue");
232
233 debug("4");
234 msgHandler.processMessage(msg);
235 debug("5");
236 mbox.notifyMonitors(msg,MailBox.RECEIVE);
237 debug("6");
238 }
239
240
241 /***
242 implement in haste, repent at leisure
243 */
244 public String getResponseAddress() {
245 return (address.toString());
246 }
247
248
249 public void debug(String str) {
250
251 }
252
253 }