/*
|
* %CopyrightBegin%
|
*
|
* Copyright Ericsson AB 2000-2009. All Rights Reserved.
|
*
|
* Licensed 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.
|
*
|
* %CopyrightEnd%
|
*/
|
package com.ericsson.otp.erlang;
|
|
import com.basic.security.utils.MyOtpConnection;
|
|
import java.io.IOException;
|
|
/**
|
* Represents an OTP node. It is used to connect to remote nodes or accept
|
* incoming connections from remote nodes.
|
* <p>
|
* <p>
|
* When the Java node will be connecting to a remote Erlang, Java or C node, it
|
* must first identify itself as a node by creating an instance of this class,
|
* after which it may connect to the remote node.
|
* <p>
|
* <p>
|
* When you create an instance of this class, it will bind a socket to a port so
|
* that incoming connections can be accepted. However the port number will not
|
* be made available to other nodes wishing to connect until you explicitely
|
* register with the port mapper daemon by calling {@link #publishPort()}.
|
* </p>
|
* <p>
|
* <pre>
|
* OtpSelf self = new OtpSelf("client", "authcookie"); // identify self
|
* OtpPeer other = new OtpPeer("server"); // identify peer
|
*
|
* OtpConnection conn = self.connect(other); // connect to peer
|
* </pre>
|
*/
|
public class OtpSelf extends OtpLocalNode {
|
private final OtpServerTransport sock;
|
private final OtpErlangPid pid;
|
|
/**
|
* <p>
|
* Create a self node using the default cookie. The default cookie is found
|
* by reading the first line of the .erlang.cookie file in the user's home
|
* directory. The home directory is obtained from the System property
|
* "user.home".
|
* </p>
|
* <p>
|
* <p>
|
* If the file does not exist, an empty string is used. This method makes no
|
* attempt to create the file.
|
* </p>
|
*
|
* @param node the name of this node.
|
* @throws IOException in case of server transport failure
|
*/
|
public OtpSelf(final String node) throws IOException {
|
this(node, defaultCookie, 0);
|
}
|
|
/**
|
* <p>
|
* Create a self node using the default cookie and custom transport factory.
|
* The default cookie is found by reading the first line of the
|
* .erlang.cookie file in the user's home directory. The home directory is
|
* obtained from the System property "user.home".
|
* </p>
|
* <p>
|
* <p>
|
* If the file does not exist, an empty string is used. This method makes no
|
* attempt to create the file.
|
* </p>
|
*
|
* @param node the name of this node.
|
* @param transportFactory the transport factory to use when creating connections.
|
* @throws IOException in case of server transport failure
|
*/
|
public OtpSelf(final String node,
|
final OtpTransportFactory transportFactory) throws IOException {
|
this(node, defaultCookie, 0, transportFactory);
|
}
|
|
/**
|
* Create a self node.
|
*
|
* @param node the name of this node.
|
* @param cookie the authorization cookie that will be used by this node when
|
* it communicates with other nodes.
|
* @throws IOException in case of server transport failure
|
*/
|
public OtpSelf(final String node, final String cookie) throws IOException {
|
this(node, cookie, 0);
|
}
|
|
/**
|
* Create a self node.
|
*
|
* @param node the name of this node.
|
* @param cookie the authorization cookie that will be used by this node when
|
* it communicates with other nodes.
|
* @param transportFactory the transport factory to use when creating connections.
|
* @throws IOException in case of server transport failure
|
*/
|
public OtpSelf(final String node, final String cookie,
|
final OtpTransportFactory transportFactory) throws IOException {
|
this(node, cookie, 0, transportFactory);
|
}
|
|
/**
|
* Create a self node.
|
*
|
* @param node the name of this node.
|
* @param cookie the authorization cookie that will be used by this node when
|
* it communicates with other nodes.
|
* @param port the port number you wish to use for incoming connections.
|
* Specifying 0 lets the system choose an available port.
|
* @throws IOException in case of server transport failure
|
*/
|
public OtpSelf(final String node, final String cookie, final int port)
|
throws IOException {
|
super(node, cookie);
|
sock = createServerTransport(port);
|
if (port != 0) {
|
this.port = port;
|
} else {
|
this.port = sock.getLocalPort();
|
}
|
pid = createPid();
|
}
|
|
/**
|
* Create a self node.
|
*
|
* @param node the name of this node.
|
* @param cookie the authorization cookie that will be used by this node when
|
* it communicates with other nodes.
|
* @param port the port number you wish to use for incoming connections.
|
* Specifying 0 lets the system choose an available port.
|
* @param transportFactory the transport factory to use when creating connections.
|
* @throws IOException in case of server transport failure
|
*/
|
public OtpSelf(final String node, final String cookie, final int port,
|
final OtpTransportFactory transportFactory) throws IOException {
|
super(node, cookie, transportFactory);
|
sock = createServerTransport(port);
|
if (port != 0) {
|
this.port = port;
|
} else {
|
this.port = sock.getLocalPort();
|
}
|
pid = createPid();
|
}
|
|
/**
|
* Get the Erlang PID that will be used as the sender id in all "anonymous"
|
* messages sent by this node. Anonymous messages are those sent via send
|
* methods in {@link OtpConnection OtpConnection} that do not specify a
|
* sender.
|
*
|
* @return the Erlang PID that will be used as the sender id in all
|
* anonymous messages sent by this node.
|
*/
|
public OtpErlangPid pid() {
|
return pid;
|
}
|
|
/**
|
* Make public the information needed by remote nodes that may wish to
|
* connect to this one. This method establishes a connection to the Erlang
|
* port mapper (Epmd) and registers the server node's name and port so that
|
* remote nodes are able to connect.
|
* <p>
|
* <p>
|
* This method will fail if an Epmd process is not running on the localhost.
|
* See the Erlang documentation for information about starting Epmd.
|
* <p>
|
* <p>
|
* Note that once this method has been called, the node is expected to be
|
* available to accept incoming connections. For that reason you should make
|
* sure that you call {@link #accept()} shortly after calling
|
* {@link #publishPort()}. When you no longer intend to accept connections
|
* you should call {@link #unPublishPort()}.
|
*
|
* @return true if the operation was successful, false if the node was
|
* already registered.
|
* @throws java.io.IOException if the port mapper could not be contacted.
|
*/
|
public boolean publishPort() throws IOException {
|
if (getEpmd() != null) {
|
return false; // already published
|
}
|
OtpEpmd.publishPort(this);
|
return getEpmd() != null;
|
}
|
|
/**
|
* Unregister the server node's name and port number from the Erlang port
|
* mapper, thus preventing any new connections from remote nodes.
|
*/
|
public void unPublishPort() {
|
// unregister with epmd
|
OtpEpmd.unPublishPort(this);
|
// close the local descriptor (if we have one)
|
try {
|
if (super.epmd != null) {
|
super.epmd.close();
|
}
|
} catch (final IOException e) {/* ignore close errors */
|
}
|
super.epmd = null;
|
}
|
|
/**
|
* Accept an incoming connection from a remote node. A call to this method
|
* will block until an incoming connection is at least attempted.
|
*
|
* @return a connection to a remote node.
|
* @throws java.io.IOException if a remote node attempted to connect but no common
|
* protocol was found.
|
* @throws OtpAuthException if a remote node attempted to connect, but was not
|
* authorized to connect.
|
*/
|
public OtpConnection accept() throws IOException, OtpAuthException {
|
OtpTransport newsock = null;
|
while (true) {
|
try {
|
newsock = sock.accept();
|
return new OtpConnection(this, newsock);
|
} catch (final IOException e) {
|
try {
|
if (newsock != null) {
|
newsock.close();
|
}
|
} catch (final IOException f) {/* ignore close errors */
|
}
|
throw e;
|
}
|
}
|
}
|
|
/**
|
* Open a connection to a remote node.
|
*
|
* @param other the remote node to which you wish to connect.
|
* @return a connection to the remote node.
|
* @throws java.net.UnknownHostException if the remote host could not be found.
|
* @throws java.io.IOException if it was not possible to connect to the remote node.
|
* @throws OtpAuthException if the connection was refused by the remote node.
|
*/
|
public MyOtpConnection connect(final OtpPeer other) throws IOException,
|
OtpAuthException {
|
return new MyOtpConnection(this, other);
|
}
|
}
|