blob: 1793988d9b6146dc18c26635e00be0ef838fd026 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.yoko.orb.OCI.IIOP;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.yoko.orb.CORBA.OutputStream;
import org.apache.yoko.orb.OB.Assert;
import org.apache.yoko.orb.OCI.IIOP.PLUGIN_ID;
import org.omg.IOP.Codec;
final class Acceptor_impl extends org.omg.CORBA.LocalObject implements
org.apache.yoko.orb.OCI.Acceptor {
// the real logger backing instance. We use the interface class as the locator
static final Logger logger = Logger.getLogger(org.apache.yoko.orb.OCI.Acceptor.class.getName());
// Some data members must not be private because the info object
// must be able to access them
public String[] hosts_; // The hosts
public java.net.ServerSocket socket_; // The socket
private boolean multiProfile_; // Use multiple profiles?
private int port_; // The port
private boolean keepAlive_; // The keepalive flag
private java.net.InetAddress localAddress_; // The local address
private final AcceptorInfo_impl info_; // Acceptor information
private ListenerMap listenMap_;
private final ConnectionHelper connectionHelper_; // plugin for managing connection config/creation
private final ExtendedConnectionHelper extendedConnectionHelper_;
private final Codec codec_;
// ------------------------------------------------------------------
// Standard IDL to Java Mapping
// ------------------------------------------------------------------
public String id() {
return PLUGIN_ID.value;
}
public int tag() {
return org.omg.IOP.TAG_INTERNET_IOP.value;
}
public int handle() {
throw new org.omg.CORBA.NO_IMPLEMENT();
}
public void close() {
logger.log(Level.FINE, "Closing server socket with host=" + localAddress_ + ", port=" + port_, new Exception("Stack trace"));
//
// Destroy the info object
//
info_._OB_destroy();
//
// Close the socket
//
try {
socket_.close();
socket_ = null;
logger.log(Level.FINE, "Closed server socket with host=" + localAddress_ + ", port=" + port_);
} catch (java.io.IOException ex) {
logger.log(Level.FINE, "Exception closing server socket with host=" + localAddress_ + ", port=" + port_, ex);
}
}
public void shutdown() {
//
// This operation does nothing in the java implementation
//
}
public void listen() {
//
// This operation does nothing in the java implementation
//
}
public org.apache.yoko.orb.OCI.Transport accept(boolean block) {
//
// Accept
//
java.net.Socket socket;
try {
//
// If non-blocking, use a timeout of 1ms
//
if (!block)
socket_.setSoTimeout(1);
else
socket_.setSoTimeout(0);
logger.fine("Accepting connection for host=" + localAddress_ + ", port=" + port_);
socket = socket_.accept();
logger.fine("Received inbound connection on socket " + socket);
} catch (java.io.InterruptedIOException ex) {
if (!block)
return null; // Timeout
else {
logger.log(Level.FINE, "Failure accepting connection for host=" + localAddress_ + ", port=" + port_, ex);
throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
org.apache.yoko.orb.OB.MinorCodes
.describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorAccept)
+ ": " + ex.getMessage(),
org.apache.yoko.orb.OB.MinorCodes.MinorAccept,
org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
}
} catch (java.io.IOException ex) {
logger.log(Level.FINE, "Failure accepting connection for host=" + localAddress_ + ", port=" + port_, ex);
throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
org.apache.yoko.orb.OB.MinorCodes
.describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorAccept)
+ ": " + ex.getMessage(),
org.apache.yoko.orb.OB.MinorCodes.MinorAccept,
org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
}
//
// Set TCP_NODELAY and SO_KEEPALIVE options
//
try {
socket.setTcpNoDelay(true);
if (keepAlive_)
socket.setKeepAlive(true);
} catch (java.net.SocketException ex) {
logger.log(Level.FINE, "Failure configuring server connection for host=" + localAddress_ + ", port=" + port_, ex);
throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
org.apache.yoko.orb.OB.MinorCodes
.describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorSetsockopt)
+ ": " + ex.getMessage(),
org.apache.yoko.orb.OB.MinorCodes.MinorSetsockopt,
org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
}
//
// Create new transport
//
org.apache.yoko.orb.OCI.Transport tr = null;
try {
tr = new Transport_impl(this, socket, listenMap_);
logger.fine("Inbound connection received from " + socket.getInetAddress());
} catch (org.omg.CORBA.SystemException ex) {
try {
socket.close();
} catch (java.io.IOException e) {
}
logger.log(Level.FINE, "error creating inbound connection", ex);
throw ex;
}
//
// Call callbacks
//
org.apache.yoko.orb.OCI.TransportInfo trInfo = tr.get_info();
try {
info_._OB_callAcceptCB(trInfo);
} catch (org.omg.CORBA.SystemException ex) {
tr.close();
logger.log(Level.FINE, "error calling connection callbacks", ex);
throw ex;
}
//
// Return new transport
//
return tr;
}
public org.apache.yoko.orb.OCI.Transport connect_self() {
//
// Create socket and connect to local address
//
java.net.Socket socket = null;
try {
if (connectionHelper_ != null) {
socket = connectionHelper_.createSelfConnection(localAddress_, port_);
} else {
socket = extendedConnectionHelper_.createSelfConnection(localAddress_, port_);
}
} catch (java.net.ConnectException ex) {
logger.log(Level.FINE, "Failure making self connection for host=" + localAddress_ + ", port=" + port_, ex);
throw new org.omg.CORBA.TRANSIENT(
org.apache.yoko.orb.OB.MinorCodes
.describeTransient(org.apache.yoko.orb.OB.MinorCodes.MinorConnectFailed)
+ ": " + ex.getMessage(),
org.apache.yoko.orb.OB.MinorCodes.MinorConnectFailed,
org.omg.CORBA.CompletionStatus.COMPLETED_NO);
} catch (java.io.IOException ex) {
logger.log(Level.FINE, "Failure making self connection for host=" + localAddress_ + ", port=" + port_, ex);
throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
org.apache.yoko.orb.OB.MinorCodes
.describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorSocket)
+ ": " + ex.getMessage(),
org.apache.yoko.orb.OB.MinorCodes.MinorSocket,
org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
}
//
// Set TCP_NODELAY option
//
try {
socket.setTcpNoDelay(true);
} catch (java.net.SocketException ex) {
logger.log(Level.FINE, "Failure configuring self connection for host=" + localAddress_ + ", port=" + port_, ex);
try {
socket.close();
} catch (java.io.IOException e) {
}
throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
org.apache.yoko.orb.OB.MinorCodes
.describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorSetsockopt)
+ ": " + ex.getMessage(),
org.apache.yoko.orb.OB.MinorCodes.MinorSetsockopt,
org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
}
//
// Create and return new transport
//
org.apache.yoko.orb.OCI.Transport tr = null;
try {
tr = new Transport_impl(this, socket, listenMap_);
} catch (org.omg.CORBA.SystemException ex) {
try {
socket.close();
} catch (java.io.IOException e) {
}
throw ex;
}
return tr;
}
public void add_profiles(org.apache.yoko.orb.OCI.ProfileInfo profileInfo,
org.apache.yoko.orb.OBPortableServer.POAPolicies policies,
org.omg.IOP.IORHolder ior) {
if (port_ == 0)
throw new RuntimeException();
//
// Filter components according to IIOP version
//
java.util.Vector components = new java.util.Vector();
if (profileInfo.major == 1 && profileInfo.minor == 0) {
//
// No components for IIOP 1.0
//
} else {
for (int i = 0; i < profileInfo.components.length; i++)
components.addElement(profileInfo.components[i]);
}
if (profileInfo.major == 1 && profileInfo.minor == 0) {
//
// For IIOP 1.0, we always add one profile for each host,
// since IIOP 1.0 doesn't support tagged components in a
// profile
//
for (int i = 0; i < hosts_.length; i++) {
org.omg.IIOP.ProfileBody_1_0 body = new org.omg.IIOP.ProfileBody_1_0();
body.iiop_version = new org.omg.IIOP.Version(profileInfo.major,
profileInfo.minor);
body.host = hosts_[i];
// the CSIv2 policy may require zeroing the port in the IOR.
if (policies.zeroPortPolicy()) {
body.port = 0;
}
else {
if (port_ >= 0x8000)
body.port = (short) (port_ - 0xffff - 1);
else
body.port = (short) port_;
}
body.object_key = profileInfo.key;
int len = ior.value.profiles.length + 1;
org.omg.IOP.TaggedProfile[] profiles = new org.omg.IOP.TaggedProfile[len];
System.arraycopy(ior.value.profiles, 0, profiles, 0,
ior.value.profiles.length);
ior.value.profiles = profiles;
ior.value.profiles[len - 1] = new org.omg.IOP.TaggedProfile();
ior.value.profiles[len - 1].tag = org.omg.IOP.TAG_INTERNET_IOP.value;
org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer();
OutputStream out = new OutputStream(buf);
out._OB_writeEndian();
org.omg.IIOP.ProfileBody_1_0Helper.write(out, body);
ior.value.profiles[len - 1].profile_data = new byte[buf
.length()];
System.arraycopy(buf.data(), 0,
ior.value.profiles[len - 1].profile_data, 0, buf
.length());
}
} else {
if (multiProfile_) {
//
// Add one profile for each host
//
for (int i = 0; i < hosts_.length; i++) {
org.omg.IIOP.ProfileBody_1_1 body = new org.omg.IIOP.ProfileBody_1_1();
body.iiop_version = new org.omg.IIOP.Version(
profileInfo.major, profileInfo.minor);
body.host = hosts_[i];
// the CSIv2 policy may require zeroing the port in the IOR.
if (policies.zeroPortPolicy()) {
body.port = 0;
}
else {
if (port_ >= 0x8000)
body.port = (short) (port_ - 0xffff - 1);
else
body.port = (short) port_;
}
body.object_key = profileInfo.key;
body.components = new org.omg.IOP.TaggedComponent[components
.size()];
components.copyInto(body.components);
int len = ior.value.profiles.length + 1;
org.omg.IOP.TaggedProfile[] profiles = new org.omg.IOP.TaggedProfile[len];
System.arraycopy(ior.value.profiles, 0, profiles, 0,
ior.value.profiles.length);
ior.value.profiles = profiles;
ior.value.profiles[len - 1] = new org.omg.IOP.TaggedProfile();
ior.value.profiles[len - 1].tag = org.omg.IOP.TAG_INTERNET_IOP.value;
org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer();
OutputStream out = new OutputStream(buf);
out._OB_writeEndian();
org.omg.IIOP.ProfileBody_1_1Helper.write(out, body);
ior.value.profiles[len - 1].profile_data = new byte[buf
.length()];
System.arraycopy(buf.data(), 0,
ior.value.profiles[len - 1].profile_data, 0, buf
.length());
}
} else {
//
// Add a single tagged profile. If there are additional
// hosts, add a tagged component for each host.
//
org.omg.IIOP.ProfileBody_1_1 body = new org.omg.IIOP.ProfileBody_1_1();
body.iiop_version = new org.omg.IIOP.Version(profileInfo.major,
profileInfo.minor);
body.host = hosts_[0];
if (policies.zeroPortPolicy()) {
body.port = 0;
}
else {
if (port_ >= 0x8000)
body.port = (short) (port_ - 0xffff - 1);
else
body.port = (short) port_;
}
body.object_key = profileInfo.key;
for (int i = 1; i < hosts_.length; i++) {
org.omg.IOP.TaggedComponent c = new org.omg.IOP.TaggedComponent();
c.tag = org.omg.IOP.TAG_ALTERNATE_IIOP_ADDRESS.value;
org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer();
OutputStream out = new OutputStream(buf);
out._OB_writeEndian();
out.write_string(hosts_[i]);
out.write_ushort(body.port);
c.component_data = new byte[buf.length()];
System.arraycopy(buf.data(), 0, c.component_data, 0, buf
.length());
components.addElement(c);
}
body.components = new org.omg.IOP.TaggedComponent[components
.size()];
components.copyInto(body.components);
int len = ior.value.profiles.length + 1;
org.omg.IOP.TaggedProfile[] profiles = new org.omg.IOP.TaggedProfile[len];
System.arraycopy(ior.value.profiles, 0, profiles, 0,
ior.value.profiles.length);
ior.value.profiles = profiles;
ior.value.profiles[len - 1] = new org.omg.IOP.TaggedProfile();
ior.value.profiles[len - 1].tag = org.omg.IOP.TAG_INTERNET_IOP.value;
org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer();
OutputStream out = new OutputStream(buf);
out._OB_writeEndian();
org.omg.IIOP.ProfileBody_1_1Helper.write(out, body);
ior.value.profiles[len - 1].profile_data = new byte[buf
.length()];
System.arraycopy(buf.data(), 0,
ior.value.profiles[len - 1].profile_data, 0, buf
.length());
}
}
}
public org.apache.yoko.orb.OCI.ProfileInfo[] get_local_profiles(
org.omg.IOP.IOR ior) {
//
// Get local profiles for all hosts
//
org.apache.yoko.orb.OCI.ProfileInfoSeqHolder profileInfoSeq = new org.apache.yoko.orb.OCI.ProfileInfoSeqHolder();
profileInfoSeq.value = new org.apache.yoko.orb.OCI.ProfileInfo[0];
for (int i = 0; i < hosts_.length; i++) {
Util.extractAllProfileInfos(ior, profileInfoSeq, true, hosts_[i],
port_, true, codec_);
}
return profileInfoSeq.value;
}
public org.apache.yoko.orb.OCI.AcceptorInfo get_info() {
return info_;
}
// ------------------------------------------------------------------
// Yoko internal functions
// Application programs must not use these functions directly
// ------------------------------------------------------------------
public Acceptor_impl(String address, String[] hosts, boolean multiProfile,
int port, int backlog, boolean keepAlive, ConnectionHelper helper, ExtendedConnectionHelper extendedConnectionHelper, ListenerMap lm, String[] params, Codec codec) {
// System.out.println("Acceptor_impl");
Assert._OB_assert((helper == null) ^ (extendedConnectionHelper == null));
hosts_ = hosts;
multiProfile_ = multiProfile;
keepAlive_ = keepAlive;
connectionHelper_ = helper;
extendedConnectionHelper_ = extendedConnectionHelper;
codec_ = codec;
info_ = new AcceptorInfo_impl(this);
listenMap_ = lm;
if (backlog == 0)
backlog = 50; // 50 is the JDK's default value
//
// Get the local address for use by connect_self
//
try {
if (address == null) {
//Since we are
// binding to all network interfaces, we'll use the loopback
// address.
localAddress_ = java.net.InetAddress.getLocalHost();
} else {
localAddress_ = java.net.InetAddress.getByName(address);
}
} catch (java.net.UnknownHostException ex) {
logger.log(Level.FINE, "Host resolution failure", ex);
throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
org.apache.yoko.orb.OB.MinorCodes
.describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorGethostbyname)
+ ": " + ex.getMessage(),
org.apache.yoko.orb.OB.MinorCodes.MinorGethostbyname,
org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
}
//
// Create socket and bind to requested network interface
//
try {
if (address == null) {
if (connectionHelper_ != null) {
socket_ = connectionHelper_.createServerSocket(port, backlog);
} else {
socket_ = extendedConnectionHelper_.createServerSocket(port, backlog, params);
}
} else {
if (connectionHelper_ != null) {
socket_ = connectionHelper_.createServerSocket(port, backlog, localAddress_);
} else {
socket_ = extendedConnectionHelper_.createServerSocket(port, backlog, localAddress_, params);
}
}
//
// Read back the port. This is needed if the port was selected by
// the operating system.
//
port_ = socket_.getLocalPort();
logger.fine("Acceptor created using socket " + socket_);
} catch (java.net.BindException ex) {
logger.log(Level.FINE, "Failure creating server socket for host=" + localAddress_ + ", port=" + port, ex);
throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
org.apache.yoko.orb.OB.MinorCodes
.describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorBind)
+ ": " + ex.getMessage(),
org.apache.yoko.orb.OB.MinorCodes.MinorBind,
org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
} catch (java.io.IOException ex) {
logger.log(Level.FINE, "Failure creating server socket for host=" + localAddress_ + ", port=" + port, ex);
throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
org.apache.yoko.orb.OB.MinorCodes
.describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorSocket)
+ ": " + ex.getMessage(),
org.apache.yoko.orb.OB.MinorCodes.MinorSocket,
org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
}
//
// Add this entry to the listenMap_ as an endpoint to remap
//
synchronized (listenMap_) {
for (int i = 0; i < hosts_.length; i++)
listenMap_.add(hosts_[i], (short) port_);
}
}
public void finalize() throws Throwable {
// System.out.println("~Acceptor_impl");
if (socket_ != null) {
close();
}
//
// remove this acceptor from the listenMap_
//
synchronized (listenMap_) {
for (int i = 0; i < hosts_.length; i++)
listenMap_.remove(hosts_[i], (short) port_);
}
super.finalize();
}
public String toString() {
return "Acceptor listening on " + socket_;
}
}