38 |
|
|
39 |
package gnu.CORBA; |
package gnu.CORBA; |
40 |
|
|
41 |
|
import gnu.CORBA.CDR.UnknownExceptionCtxHandler; |
42 |
import gnu.CORBA.CDR.cdrBufInput; |
import gnu.CORBA.CDR.cdrBufInput; |
43 |
import gnu.CORBA.CDR.cdrBufOutput; |
import gnu.CORBA.CDR.cdrBufOutput; |
44 |
import gnu.CORBA.GIOP.CloseMessage; |
import gnu.CORBA.GIOP.CloseMessage; |
53 |
import org.omg.CORBA.BAD_OPERATION; |
import org.omg.CORBA.BAD_OPERATION; |
54 |
import org.omg.CORBA.BAD_PARAM; |
import org.omg.CORBA.BAD_PARAM; |
55 |
import org.omg.CORBA.CompletionStatus; |
import org.omg.CORBA.CompletionStatus; |
|
import org.omg.CORBA.DATA_CONVERSION; |
|
56 |
import org.omg.CORBA.MARSHAL; |
import org.omg.CORBA.MARSHAL; |
57 |
import org.omg.CORBA.NO_RESOURCES; |
import org.omg.CORBA.NO_RESOURCES; |
58 |
import org.omg.CORBA.OBJECT_NOT_EXIST; |
import org.omg.CORBA.OBJECT_NOT_EXIST; |
|
import org.omg.CORBA.Object; |
|
|
import org.omg.CORBA.ORBPackage.InvalidName; |
|
59 |
import org.omg.CORBA.Request; |
import org.omg.CORBA.Request; |
60 |
import org.omg.CORBA.SystemException; |
import org.omg.CORBA.SystemException; |
61 |
import org.omg.CORBA.UNKNOWN; |
import org.omg.CORBA.UNKNOWN; |
62 |
import org.omg.CORBA.WrongTransaction; |
import org.omg.CORBA.WrongTransaction; |
63 |
|
import org.omg.CORBA.ORBPackage.InvalidName; |
64 |
import org.omg.CORBA.portable.Delegate; |
import org.omg.CORBA.portable.Delegate; |
65 |
import org.omg.CORBA.portable.InvokeHandler; |
import org.omg.CORBA.portable.InvokeHandler; |
66 |
import org.omg.CORBA.portable.ObjectImpl; |
import org.omg.CORBA.portable.ObjectImpl; |
67 |
|
import org.omg.CORBA.portable.UnknownException; |
68 |
import org.omg.CosNaming.NamingContextExt; |
import org.omg.CosNaming.NamingContextExt; |
69 |
import org.omg.CosNaming.NamingContextExtHelper; |
import org.omg.CosNaming.NamingContextExtHelper; |
70 |
|
|
71 |
import java.applet.Applet; |
import java.applet.Applet; |
|
|
|
72 |
import java.io.IOException; |
import java.io.IOException; |
73 |
import java.io.InputStream; |
import java.io.InputStream; |
74 |
import java.io.OutputStream; |
import java.io.OutputStream; |
|
|
|
75 |
import java.net.InetAddress; |
import java.net.InetAddress; |
76 |
import java.net.ServerSocket; |
import java.net.ServerSocket; |
77 |
import java.net.Socket; |
import java.net.Socket; |
78 |
import java.net.SocketException; |
import java.net.SocketException; |
79 |
import java.net.UnknownHostException; |
import java.net.UnknownHostException; |
|
|
|
80 |
import java.util.ArrayList; |
import java.util.ArrayList; |
81 |
import java.util.Enumeration; |
import java.util.Enumeration; |
82 |
import java.util.Hashtable; |
import java.util.Hashtable; |
84 |
import java.util.LinkedList; |
import java.util.LinkedList; |
85 |
import java.util.Map; |
import java.util.Map; |
86 |
import java.util.Properties; |
import java.util.Properties; |
87 |
|
import java.util.Random; |
88 |
import java.util.StringTokenizer; |
import java.util.StringTokenizer; |
89 |
import java.util.TreeMap; |
import java.util.TreeMap; |
90 |
|
|
108 |
/** |
/** |
109 |
* The number of the currently running parallel threads. |
* The number of the currently running parallel threads. |
110 |
*/ |
*/ |
111 |
int running_threads; |
int running_threads; |
112 |
|
|
113 |
/** |
/** |
114 |
* The port on that this portServer is listening for requests. |
* The port on that this portServer is listening for requests. |
131 |
portServer(int _port) |
portServer(int _port) |
132 |
{ |
{ |
133 |
s_port = _port; |
s_port = _port; |
134 |
|
setDaemon(true); |
135 |
} |
} |
136 |
|
|
137 |
/** |
/** |
147 |
catch (IOException ex) |
catch (IOException ex) |
148 |
{ |
{ |
149 |
BAD_OPERATION bad = |
BAD_OPERATION bad = |
150 |
new BAD_OPERATION("Unable to open the server socket."); |
new BAD_OPERATION("Unable to open the server socket at "+s_port); |
151 |
bad.initCause(ex); |
bad.initCause(ex); |
152 |
throw bad; |
throw bad; |
153 |
} |
} |
167 |
} |
} |
168 |
catch (Exception iex) |
catch (Exception iex) |
169 |
{ |
{ |
170 |
// Wait 5 seconds. Do not terminate the |
// Wait. Do not terminate the |
171 |
// service due potentially transient error. |
// service due potentially transient error. |
172 |
try |
try |
173 |
{ |
{ |
174 |
Thread.sleep(5000); |
Thread.sleep(TWAIT_SERVER_ERROR_PAUSE); |
175 |
} |
} |
176 |
catch (InterruptedException ex) |
catch (InterruptedException ex) |
177 |
{ |
{ |
248 |
* for a free port. |
* for a free port. |
249 |
*/ |
*/ |
250 |
public static int DEFAULT_INITIAL_PORT = 1126; |
public static int DEFAULT_INITIAL_PORT = 1126; |
251 |
|
|
252 |
|
/** |
253 |
|
* When trying to open the socket on a random port, start of the interval to |
254 |
|
* try. |
255 |
|
*/ |
256 |
|
public static int RANDOM_PORT_FROM = 1024; |
257 |
|
|
258 |
|
/** |
259 |
|
* When trying to open the socket on a random port, end of the interval to |
260 |
|
* try. |
261 |
|
*/ |
262 |
|
public static int RANDOM_PORT_TO = 4024; |
263 |
|
|
264 |
|
/** |
265 |
|
* The number of attempts to try when opening random port. |
266 |
|
*/ |
267 |
|
public static int RANDOM_PORT_ATTEMPTS = 64; |
268 |
|
|
269 |
/** |
/** |
270 |
* The property of port, on that this ORB is listening for requests from |
* The property of port, on that this ORB is listening for requests from |
293 |
* The string, defining the naming service initial reference. |
* The string, defining the naming service initial reference. |
294 |
*/ |
*/ |
295 |
public static final String NAME_SERVICE = "NameService"; |
public static final String NAME_SERVICE = "NameService"; |
296 |
|
|
297 |
/** |
/** |
298 |
* The if the client has once opened a socket, it should start sending the |
* The if the client has once opened a socket, it should start sending the |
299 |
* message header in a given time. Otherwise the server will close the socket. |
* message header in a given time. Otherwise the server will close the socket. |
317 |
*/ |
*/ |
318 |
public static String AFTER_RECEIVING = |
public static String AFTER_RECEIVING = |
319 |
"gnu.classpath.CORBA.TOUT_AFTER_RECEIVING"; |
"gnu.classpath.CORBA.TOUT_AFTER_RECEIVING"; |
320 |
|
|
321 |
|
/** |
322 |
|
* The server waits for this duration after the potentially transient error |
323 |
|
* during its servicing cycle. |
324 |
|
*/ |
325 |
|
public static String SERVER_ERROR_PAUSE = |
326 |
|
"gnu.classpath.CORBA.SERVER_ERROR_PAUSE"; |
327 |
|
|
328 |
/** |
/** |
329 |
* The address of the local host. |
* The address of the local host. |
336 |
* This prevents server hang when the client opens the socket, but does not |
* This prevents server hang when the client opens the socket, but does not |
337 |
* send any message, usually due crash on the client side. |
* send any message, usually due crash on the client side. |
338 |
*/ |
*/ |
339 |
private int TOUT_START_READING_MESSAGE = 20 * 1000; |
public int TOUT_START_READING_MESSAGE = 20 * 1000; |
340 |
|
|
341 |
// (Here and below, we use * to make the meaning of the constant clearler). |
// (Here and below, we use * to make the meaning of the constant clearler). |
342 |
|
|
344 |
* If the client has started to send the request message, the socket time out |
* If the client has started to send the request message, the socket time out |
345 |
* changes to the specified value. |
* changes to the specified value. |
346 |
*/ |
*/ |
347 |
private int TOUT_WHILE_READING = 2 * 60 * 1000; |
public int TOUT_WHILE_READING = 2 * 60 * 1000; |
348 |
|
|
349 |
/** |
/** |
350 |
* If the message body is received, the time out changes to the specifice |
* If the message body is received, the time out changes to the specifice |
351 |
* value. This must be longer, as includes time, required to process the |
* value. This must be longer, as includes time, required to process the |
352 |
* received task. We make it 40 minutes. |
* received task. We make it 40 minutes. |
353 |
*/ |
*/ |
354 |
private int TOUT_AFTER_RECEIVING = 40 * 60 * 1000; |
public int TOUT_AFTER_RECEIVING = 40 * 60 * 1000; |
355 |
|
|
356 |
|
/** |
357 |
|
* The server waits for this duration after the potentially transient error |
358 |
|
* during its servicing cycle. |
359 |
|
*/ |
360 |
|
public int TWAIT_SERVER_ERROR_PAUSE = 5000; |
361 |
|
|
362 |
/** |
/** |
363 |
* Some clients tend to submit multiple requests over the same socket. The |
* Some clients tend to submit multiple requests over the same socket. The |
486 |
/** |
/** |
487 |
* Get the currently free port, starting from the initially set port and going |
* Get the currently free port, starting from the initially set port and going |
488 |
* up max 20 steps, then trying to bind into any free address. |
* up max 20 steps, then trying to bind into any free address. |
489 |
* |
* |
490 |
* @return the currently available free port. |
* @return the currently available free port. |
491 |
* |
* |
492 |
* @throws NO_RESOURCES if the server socked cannot be opened on the local |
* @throws NO_RESOURCES if the server socked cannot be opened on the local |
493 |
* host. |
* host. |
494 |
*/ |
*/ |
495 |
public int getFreePort() throws BAD_OPERATION |
public int getFreePort() |
496 |
|
throws BAD_OPERATION |
497 |
{ |
{ |
498 |
ServerSocket s; |
ServerSocket s; |
499 |
int a_port; |
int a_port; |
532 |
} |
} |
533 |
} |
} |
534 |
|
|
535 |
|
Random rand = new Random(); |
536 |
|
// Try any random port in the interval RANDOM_PORT_FROM.RANDOM_PORT_TO. |
537 |
|
int range = RANDOM_PORT_TO - RANDOM_PORT_FROM; |
538 |
|
for (int i = 0; i < RANDOM_PORT_ATTEMPTS; i++) |
539 |
|
{ |
540 |
|
try |
541 |
|
{ |
542 |
|
a_port = RANDOM_PORT_FROM |
543 |
|
+ rand.nextInt(range); |
544 |
|
s = new ServerSocket(a_port); |
545 |
|
s.close(); |
546 |
|
return a_port; |
547 |
|
} |
548 |
|
catch (IOException ex) |
549 |
|
{ |
550 |
|
// Repeat the loop if this exception has been thrown. |
551 |
|
} |
552 |
|
} |
553 |
|
|
554 |
try |
try |
555 |
{ |
{ |
556 |
// Try any port. |
// Try the parameterless constructor. |
557 |
s = new ServerSocket(); |
s = new ServerSocket(); |
558 |
a_port = s.getLocalPort(); |
a_port = s.getLocalPort(); |
559 |
s.close(); |
s.close(); |
561 |
} |
} |
562 |
catch (IOException ex) |
catch (IOException ex) |
563 |
{ |
{ |
564 |
NO_RESOURCES bad = |
NO_RESOURCES bad = new NO_RESOURCES("Unable to open the server socket."); |
|
new NO_RESOURCES("Unable to open the server socket."); |
|
565 |
bad.initCause(ex); |
bad.initCause(ex); |
566 |
throw bad; |
throw bad; |
567 |
} |
} |
804 |
if (!ior.Internet.host.equals(LOCAL_HOST)) |
if (!ior.Internet.host.equals(LOCAL_HOST)) |
805 |
return null; |
return null; |
806 |
|
|
807 |
// Must be the same port. |
return find_connected_object(ior.key, ior.Internet.port); |
|
if (ior.Internet.port != Port) |
|
|
return null; |
|
|
|
|
|
return find_connected_object(ior.key); |
|
808 |
} |
} |
809 |
|
|
810 |
/** |
/** |
943 |
} |
} |
944 |
else |
else |
945 |
subserver = (portServer) identities.get(obj.identity); |
subserver = (portServer) identities.get(obj.identity); |
946 |
|
|
947 |
if (!subserver.isAlive()) |
if (!subserver.isAlive()) |
948 |
{ |
{ |
949 |
// Reuse the current thread for the last portServer. |
// Reuse the current thread for the last portServer. |
959 |
} |
} |
960 |
} |
} |
961 |
} |
} |
962 |
|
|
963 |
|
/** |
964 |
|
* Start the server in a new thread, if not already running. This method is |
965 |
|
* used to ensure that the objects being transfered will be served fro the |
966 |
|
* remote side, if required. If the ORB is started using this method, it |
967 |
|
* starts as a daemon thread. |
968 |
|
*/ |
969 |
|
public void ensureRunning() |
970 |
|
{ |
971 |
|
final Functional_ORB THIS = this; |
972 |
|
|
973 |
|
if (!running) |
974 |
|
{ |
975 |
|
Thread t = new Thread() |
976 |
|
{ |
977 |
|
public void run() |
978 |
|
{ |
979 |
|
THIS.run(); |
980 |
|
} |
981 |
|
}; |
982 |
|
t.setDaemon(true); |
983 |
|
t.start(); |
984 |
|
} |
985 |
|
} |
986 |
|
|
987 |
/** |
/** |
988 |
* Shutdown the ORB server. |
* Shutdown the ORB server. |
1043 |
} |
} |
1044 |
|
|
1045 |
object = impl; |
object = impl; |
1046 |
connected_objects.add(ior.key, impl, ior.Internet.port, null); |
// TODO remove commented out code below. |
1047 |
|
// connected_objects.add(ior.key, impl, ior.Internet.port, null); |
1048 |
} |
} |
1049 |
return object; |
return object; |
1050 |
} |
} |
1073 |
/** |
/** |
1074 |
* Find and return the object, that must be previously connected to this ORB. |
* Find and return the object, that must be previously connected to this ORB. |
1075 |
* Return null if no such object is available. |
* Return null if no such object is available. |
1076 |
* |
* |
1077 |
* @param key the object key. |
* @param key the object key. |
1078 |
* |
* @param port the port where the object is connected. |
1079 |
|
* |
1080 |
* @return the connected object, null if none. |
* @return the connected object, null if none. |
1081 |
*/ |
*/ |
1082 |
protected org.omg.CORBA.Object find_connected_object(byte[] key) |
protected org.omg.CORBA.Object find_connected_object(byte[] key, int port) |
1083 |
{ |
{ |
1084 |
Connected_objects.cObject ref = connected_objects.get(key); |
Connected_objects.cObject ref = connected_objects.get(key); |
1085 |
return ref == null ? null : ref.object; |
if (ref == null) |
1086 |
|
return null; |
1087 |
|
if (port >= 0 && ref.port != port) |
1088 |
|
return null; |
1089 |
|
else |
1090 |
|
return ref.object; |
1091 |
} |
} |
1092 |
|
|
1093 |
/** |
/** |
1399 |
|
|
1400 |
/** |
/** |
1401 |
* A single servicing step, when the client socket is alrady open. |
* A single servicing step, when the client socket is alrady open. |
1402 |
* |
* |
1403 |
* Normally, each task matches a single remote invocation. However under |
* Normally, each task matches a single remote invocation. However under |
1404 |
* frequent tandem submissions the same task may span over several |
* frequent tandem submissions the same task may span over several |
1405 |
* invocations. |
* invocations. |
1406 |
* |
* |
1407 |
* @param service the opened client socket. |
* @param service the opened client socket. |
1408 |
* @param no_resources if true, the "NO RESOURCES" exception is thrown to the |
* @param no_resources if true, the "NO RESOURCES" exception is thrown to the |
1409 |
* client. |
* client. |
1412 |
{ |
{ |
1413 |
try |
try |
1414 |
{ |
{ |
1415 |
Serving: |
Serving: while (true) |
|
while (true) |
|
1416 |
{ |
{ |
1417 |
InputStream in = service.getInputStream(); |
InputStream in = service.getInputStream(); |
1418 |
service.setSoTimeout(TOUT_START_READING_MESSAGE); |
service.setSoTimeout(TOUT_START_READING_MESSAGE); |
1432 |
if (max_version != null) |
if (max_version != null) |
1433 |
{ |
{ |
1434 |
if (!msh_request.version.until_inclusive(max_version.major, |
if (!msh_request.version.until_inclusive(max_version.major, |
1435 |
max_version.minor |
max_version.minor)) |
|
) |
|
|
) |
|
1436 |
{ |
{ |
1437 |
OutputStream out = service.getOutputStream(); |
OutputStream out = service.getOutputStream(); |
1438 |
new ErrorMessage(max_version).write(out); |
new ErrorMessage(max_version).write(out); |
1440 |
} |
} |
1441 |
} |
} |
1442 |
|
|
1443 |
byte[] r = new byte[ msh_request.message_size ]; |
byte[] r = msh_request.readMessage(in, service, TOUT_WHILE_READING, |
1444 |
|
TOUT_AFTER_RECEIVING); |
|
int n = 0; |
|
|
|
|
|
service.setSoTimeout(TOUT_WHILE_READING); |
|
|
|
|
|
reading: |
|
|
while (n < r.length) |
|
|
{ |
|
|
n += in.read(r, n, r.length - n); |
|
|
} |
|
|
|
|
|
service.setSoTimeout(TOUT_AFTER_RECEIVING); |
|
1445 |
|
|
1446 |
if (msh_request.message_type == MessageHeader.REQUEST) |
if (msh_request.message_type == MessageHeader.REQUEST) |
1447 |
{ |
{ |
1467 |
// find the target object. |
// find the target object. |
1468 |
} |
} |
1469 |
|
|
1470 |
InvokeHandler target = |
InvokeHandler target = (InvokeHandler) find_connected_object( |
1471 |
(InvokeHandler) find_connected_object(rh_request.object_key); |
rh_request.object_key, -1); |
1472 |
|
|
1473 |
// Prepare the reply header. This must be done in advance, |
// Prepare the reply header. This must be done in advance, |
1474 |
// as the size must be known for handler to set alignments |
// as the size must be known for handler to set alignments |
1476 |
ReplyHeader rh_reply = msh_request.create_reply_header(); |
ReplyHeader rh_reply = msh_request.create_reply_header(); |
1477 |
|
|
1478 |
// TODO log errors about not existing objects and methods. |
// TODO log errors about not existing objects and methods. |
1479 |
bufferedResponseHandler handler = |
bufferedResponseHandler handler = new bufferedResponseHandler( |
1480 |
new bufferedResponseHandler(this, msh_request, rh_reply, |
this, msh_request, rh_reply, rh_request); |
|
rh_request |
|
|
); |
|
1481 |
|
|
1482 |
SystemException sysEx = null; |
SystemException sysEx = null; |
1483 |
|
|
1501 |
continue Serving; |
continue Serving; |
1502 |
} |
} |
1503 |
} |
} |
1504 |
|
catch (UnknownException uex) |
1505 |
|
{ |
1506 |
|
sysEx = new UNKNOWN("Unknown", 2, |
1507 |
|
CompletionStatus.COMPLETED_MAYBE); |
1508 |
|
sysEx.initCause(uex.originalEx); |
1509 |
|
|
1510 |
|
org.omg.CORBA.portable.OutputStream ech = handler.createExceptionReply(); |
1511 |
|
|
1512 |
|
rh_reply.service_context = UnknownExceptionCtxHandler.addExceptionContext( |
1513 |
|
rh_reply.service_context, uex.originalEx, ech); |
1514 |
|
|
1515 |
|
ObjectCreator.writeSystemException(ech, sysEx); |
1516 |
|
} |
1517 |
catch (SystemException ex) |
catch (SystemException ex) |
1518 |
{ |
{ |
1519 |
sysEx = ex; |
sysEx = ex; |
1520 |
|
|
1521 |
org.omg.CORBA.portable.OutputStream ech = |
org.omg.CORBA.portable.OutputStream ech = handler.createExceptionReply(); |
1522 |
handler.createExceptionReply(); |
|
1523 |
|
rh_reply.service_context = UnknownExceptionCtxHandler.addExceptionContext( |
1524 |
|
rh_reply.service_context, ex, ech); |
1525 |
|
|
1526 |
ObjectCreator.writeSystemException(ech, ex); |
ObjectCreator.writeSystemException(ech, ex); |
1527 |
} |
} |
1528 |
catch (Exception except) |
catch (Exception except) |
1529 |
{ |
{ |
1530 |
|
// This should never happen under normal operation and |
1531 |
|
// can only indicate errors in user object implementation. |
1532 |
|
// We inform the user. |
1533 |
except.printStackTrace(); |
except.printStackTrace(); |
|
sysEx = |
|
|
new UNKNOWN("Unknown", 2, |
|
|
CompletionStatus.COMPLETED_MAYBE |
|
|
); |
|
1534 |
|
|
1535 |
org.omg.CORBA.portable.OutputStream ech = |
sysEx = new UNKNOWN("Unknown", 2, |
1536 |
handler.createExceptionReply(); |
CompletionStatus.COMPLETED_MAYBE); |
1537 |
|
sysEx.initCause(except); |
1538 |
|
|
1539 |
|
org.omg.CORBA.portable.OutputStream ech = handler.createExceptionReply(); |
1540 |
|
|
1541 |
|
rh_reply.service_context = UnknownExceptionCtxHandler.addExceptionContext( |
1542 |
|
rh_reply.service_context, except, ech); |
1543 |
|
|
1544 |
ObjectCreator.writeSystemException(ech, sysEx); |
ObjectCreator.writeSystemException(ech, sysEx); |
1545 |
} |
} |
1549 |
{ |
{ |
1550 |
OutputStream sou = service.getOutputStream(); |
OutputStream sou = service.getOutputStream(); |
1551 |
respond_to_client(sou, msh_request, rh_request, handler, |
respond_to_client(sou, msh_request, rh_request, handler, |
1552 |
sysEx |
sysEx); |
|
); |
|
1553 |
} |
} |
1554 |
} |
} |
1555 |
else if (msh_request.message_type == MessageHeader.CLOSE_CONNECTION || |
else if (msh_request.message_type == MessageHeader.CLOSE_CONNECTION |
1556 |
msh_request.message_type == MessageHeader.MESSAGE_ERROR |
|| msh_request.message_type == MessageHeader.MESSAGE_ERROR) |
|
) |
|
1557 |
{ |
{ |
1558 |
CloseMessage.close(service.getOutputStream()); |
CloseMessage.close(service.getOutputStream()); |
1559 |
service.close(); |
service.close(); |
1560 |
return; |
return; |
1561 |
} |
} |
|
; |
|
1562 |
|
|
|
// TODO log error: "Not a request message." |
|
1563 |
if (service != null && !service.isClosed()) |
if (service != null && !service.isClosed()) |
1564 |
|
|
1565 |
// Wait for the subsequent invocations on the |
// Wait for the subsequent invocations on the |
1603 |
if (props.containsKey(AFTER_RECEIVING)) |
if (props.containsKey(AFTER_RECEIVING)) |
1604 |
TOUT_AFTER_RECEIVING = |
TOUT_AFTER_RECEIVING = |
1605 |
Integer.parseInt(props.getProperty(AFTER_RECEIVING)); |
Integer.parseInt(props.getProperty(AFTER_RECEIVING)); |
1606 |
|
if (props.containsKey(SERVER_ERROR_PAUSE)) |
1607 |
|
TWAIT_SERVER_ERROR_PAUSE = |
1608 |
|
Integer.parseInt(props.getProperty(SERVER_ERROR_PAUSE)); |
1609 |
} |
} |
1610 |
catch (NumberFormatException ex) |
catch (NumberFormatException ex) |
1611 |
{ |
{ |