View Javadoc

1   /*
2    * The contents of this file are subject to the BT "ZEUS" Open Source
3    * Licence (L77741), Version 1.0 (the "Licence"); you may not use this file
4    * except in compliance with the Licence. You may obtain a copy of the Licence
5    * from $ZEUS_INSTALL/licence.html or alternatively from
6    * http://www.labs.bt.com/projects/agents/zeus/licence.htm
7    *
8    * Except as stated in Clause 7 of the Licence, software distributed under the
9    * Licence is distributed WITHOUT WARRANTY OF ANY KIND, either express or
10   * implied. See the Licence for the specific language governing rights and
11   * limitations under the Licence.
12   *
13   * The Original Code is within the package zeus.*.
14   * The Initial Developer of the Original Code is British Telecommunications
15   * public limited company, whose registered office is at 81 Newgate Street,
16   * London, EC1A 7AJ, England. Portions created by British Telecommunications
17   * public limited company are Copyright 1996-9. All Rights Reserved.
18   *
19   * THIS NOTICE MUST BE INCLUDED ON ANY COPY OF THIS FILE
20   */
21  
22  
23  
24  /*
25   * @(#)Server.java 1.3
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
50      public static final int DEFAULT_PORT_MIN = 6700;//6700
51      public static final int DEFAULT_PORT_MAX = 7800;//6800
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      // added so that the class can be extended without starting the threads.
78      public Server() { ; }
79      
80      
81      
82      public Server(AgentContext context, MailBox mbox, Queue inMail) {
83          Assert.notNull(context);
84          this.context = context;
85          // Get localhost details
86          try {
87              InetAddress ip = InetAddress.getLocalHost();
88              String localhost = ip.getHostAddress();
89              Core.DEBUG(4,"Ip Address is: " + ip);
90              
91              // Select port for listening
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                     // e.printStackTrace();
104                 }
105             }
106             if ( !port_found ) {
107                 System.err.println("Cannot get a port for listening");
108                 //  System.exit(0);
109             }
110         }
111         catch (UnknownHostException e) {
112             System.err.println("Cannot get local host IP address");
113             //System.exit(0);
114         }
115         catch (IOException e) {
116             System.err.println("Cannot get a port for listening");
117             e.printStackTrace();
118             // System.exit(0);
119         }
120         
121         // Store variables
122         //  this.inMail = inMail;
123         this.mbox = mbox;
124         
125         // LL 030500 1.03b
126         // lowerStatus();
127         
128         // Start the server listening for connections
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     // LL 030500 1.03bB
157     public void normalStatus() {
158         this.setPriority(Thread.NORM_PRIORITY);
159         timeout = 1000;//1000?
160     }
161     // LL 030500 1.03bE
162     
163     // The body of the server thread.  Loop forever, listening for and
164     // accepting connections from clients.  For each connection,
165     // create a Connection object to handle communication through the
166     // new Socket.
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             // extra catches inserted by Simon on 4/6/03 to give enhanced confidence. 
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         // add this agent to the addressbook
219         debug("2");
220         if ( (addr = msg.getAddress()) != null )
221             if (!addr.getType().equalsIgnoreCase("FORWARD"))
222                 context.AddressBook().add(addr);
223         
224         // if (inMail == null){
225         debug("3");
226         if (msgHandler==null)
227             msgHandler = context.getMsgHandler();
228         //	     inMail = msgHandler.getMessageQueue();
229         //}
230         
231         Core.DEBUG(3,"putting message from " + msg.getSender() + " on handler queue");
232         //inMail.enqueue(msg);
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        //   System.out.println("Server>> " + str);
251     }
252     
253 }