aboutsummaryrefslogtreecommitdiffstats
path: root/lib/erl_interface/src/epmd
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
committerErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
commit84adefa331c4159d432d22840663c38f155cd4c1 (patch)
treebff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/erl_interface/src/epmd
downloadotp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz
otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2
otp-84adefa331c4159d432d22840663c38f155cd4c1.zip
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/erl_interface/src/epmd')
-rw-r--r--lib/erl_interface/src/epmd/ei_epmd.h66
-rw-r--r--lib/erl_interface/src/epmd/epmd_port.c299
-rw-r--r--lib/erl_interface/src/epmd/epmd_publish.c228
-rw-r--r--lib/erl_interface/src/epmd/epmd_unpublish.c106
4 files changed, 699 insertions, 0 deletions
diff --git a/lib/erl_interface/src/epmd/ei_epmd.h b/lib/erl_interface/src/epmd/ei_epmd.h
new file mode 100644
index 0000000000..40e5ece572
--- /dev/null
+++ b/lib/erl_interface/src/epmd/ei_epmd.h
@@ -0,0 +1,66 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+#ifndef _EI_EPMD_H
+#define _EI_EPMD_H
+
+#ifndef INADDR_LOOPBACK
+#define INADDR_LOOPBACK ((u_long) 0x7F000001)
+#endif
+
+#ifndef EI_DIST_HIGH
+#define EI_DIST_HIGH 5 /* R4 and later */
+#define EI_DIST_LOW 1 /* R3 and earlier */
+#endif
+
+#ifndef EPMD_PORT
+#define EPMD_PORT 4369
+#endif
+
+#ifndef EPMDBUF
+#define EPMDBUF 512
+#endif
+
+#ifndef EI_MYPROTO
+#define EI_MYPROTO 0 /* tcp/ip */
+#endif
+
+/* epmd r3 protocol */
+#ifndef EI_EPMD_ALIVE_REQ
+#define EI_EPMD_ALIVE_REQ 'a'
+#define EI_EPMD_ALIVE_OK_RESP 'Y'
+#define EI_EPMD_PORT_REQ 'p'
+#define EI_EPMD_STOP_REQ 's'
+#endif
+
+/* epmd r4 */
+#ifndef EI_EPMD_ALIVE2_REQ
+#define EI_EPMD_ALIVE2_REQ 120
+#define EI_EPMD_ALIVE2_RESP 121
+#define EI_EPMD_PORT2_REQ 122
+#define EI_EPMD_PORT2_RESP 119
+#endif
+
+/* internal functions */
+int ei_epmd_connect_tmo(struct in_addr *inaddr, unsigned ms);
+int ei_epmd_publish(int port, const char *alive);
+int ei_epmd_publish_tmo(int port, const char *alive, unsigned ms);
+int ei_epmd_port(struct in_addr *inaddr, const char *alive, int *dist);
+int ei_epmd_port_tmo(struct in_addr *inaddr, const char *alive, int *dist, unsigned ms);
+
+#endif /* _EI_EPMD_H */
diff --git a/lib/erl_interface/src/epmd/epmd_port.c b/lib/erl_interface/src/epmd/epmd_port.c
new file mode 100644
index 0000000000..663b38d2d4
--- /dev/null
+++ b/lib/erl_interface/src/epmd/epmd_port.c
@@ -0,0 +1,299 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#include "eidef.h"
+
+#ifdef __WIN32__
+#include <winsock2.h>
+#include <windows.h>
+#include <winbase.h>
+
+#elif VXWORKS
+#include <vxWorks.h>
+#include <ifLib.h>
+#include <sockLib.h>
+#include <inetLib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#else
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "ei.h"
+#include "ei_internal.h"
+#include "ei_epmd.h"
+#include "ei_portio.h"
+#include "putget.h"
+
+
+/* connect to epmd on given host (use NULL for localhost) */
+/*
+ * FIXME: Expects IPv4 addresses (excludes IPv6, Appletalk, IRDA and
+ * whatever) */
+int ei_epmd_connect_tmo(struct in_addr *inaddr, unsigned ms)
+{
+ static unsigned int epmd_port = 0;
+ struct sockaddr_in saddr;
+ int sd;
+ int res;
+
+ if (epmd_port == 0) {
+ char* port_str = getenv("ERL_EPMD_PORT");
+ epmd_port = (port_str != NULL) ? atoi(port_str) : EPMD_PORT;
+ }
+ memset(&saddr, 0, sizeof(saddr));
+ saddr.sin_port = htons(epmd_port);
+ saddr.sin_family = AF_INET;
+
+ if (!inaddr) saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ else memmove(&saddr.sin_addr,inaddr,sizeof(saddr.sin_addr));
+
+ if (((sd = socket(PF_INET, SOCK_STREAM, 0)) < 0))
+ {
+ erl_errno = errno;
+ return -1;
+ }
+
+ if ((res = ei_connect_t(sd,(struct sockaddr *)&saddr,sizeof(saddr),ms)) < 0)
+ {
+ erl_errno = (res == -2) ? ETIMEDOUT : errno;
+ closesocket(sd);
+ return -1;
+ }
+
+ return sd;
+}
+
+/* get the given node's listen port using old epmd protocol */
+static int ei_epmd_r3_port (struct in_addr *addr, const char *alive,
+ unsigned ms)
+{
+ char buf[EPMDBUF];
+ char *s = buf;
+ int len = strlen(alive) + 1;
+ int fd;
+ int port;
+ int res;
+#if defined(VXWORKS)
+ char ntoabuf[32];
+#endif
+
+ put16be(s,len);
+ put8(s,EI_EPMD_PORT_REQ);
+ strcpy(s,alive);
+
+ /* connect to epmd */
+ if ((fd = ei_epmd_connect_tmo(addr,ms)) < 0)
+ {
+ /* ei_epmd_connect_tmo() sets erl_errno */
+ return -1;
+ }
+
+ if ((res = ei_write_fill_t(fd, buf, len+2, ms)) != len+2) {
+ closesocket(fd);
+ erl_errno = (res == -2) ? ETIMEDOUT : EIO;
+ return -1;
+ }
+
+#ifdef VXWORKS
+ /* FIXME use union/macro for level. Correct level? */
+ if (ei_tracelevel > 2) {
+ inet_ntoa_b(*addr,ntoabuf);
+ EI_TRACE_CONN2("ei_epmd_r3_port",
+ "-> PORT_REQ alive=%s ip=%s",alive,ntoabuf);
+ }
+#else
+ EI_TRACE_CONN2("ei_epmd_r3_port",
+ "-> PORT_REQ alive=%s ip=%s",alive,inet_ntoa(*addr));
+#endif
+
+ if ((res = ei_read_fill_t(fd, buf, 2, ms)) != 2) {
+ EI_TRACE_ERR0("ei_epmd_r3_port","<- CLOSE");
+ closesocket(fd);
+ erl_errno = (res == -2) ? ETIMEDOUT : EIO;
+ return -1;
+ }
+ closesocket(fd);
+ s = buf;
+ port = get16be(s);
+
+ EI_TRACE_CONN1("ei_epmd_r3_port","<- PORT_RESP port=%d",port);
+
+ return port;
+}
+
+static int ei_epmd_r4_port (struct in_addr *addr, const char *alive,
+ int *dist, unsigned ms)
+{
+ char buf[EPMDBUF];
+ char *s = buf;
+ int len = strlen(alive) + 1;
+ int fd;
+ int ntype;
+ int port;
+ int dist_high, dist_low, proto;
+ int res;
+#if defined(VXWORKS)
+ char ntoabuf[32];
+#endif
+
+ put16be(s,len);
+ put8(s,EI_EPMD_PORT2_REQ);
+ strcpy(s,alive);
+
+ /* connect to epmd */
+ if ((fd = ei_epmd_connect_tmo(addr,ms)) < 0)
+ {
+ return -1;
+ }
+
+ if ((res = ei_write_fill_t(fd, buf, len+2, ms)) != len+2) {
+ closesocket(fd);
+ erl_errno = (res == -2) ? ETIMEDOUT : EIO;
+ return -1;
+ }
+
+#ifdef VXWORKS
+ /* FIXME use union/macro for level. Correct level? */
+ if (ei_tracelevel > 2) {
+ inet_ntoa_b(*addr,ntoabuf);
+ EI_TRACE_CONN2("ei_epmd_r4_port",
+ "-> PORT2_REQ alive=%s ip=%s",alive,ntoabuf);
+ }
+#else
+ EI_TRACE_CONN2("ei_epmd_r4_port",
+ "-> PORT2_REQ alive=%s ip=%s",alive,inet_ntoa(*addr));
+#endif
+
+ /* read first two bytes (response type, response) */
+ if ((res = ei_read_fill_t(fd, buf, 2, ms)) != 2) {
+ EI_TRACE_ERR0("ei_epmd_r4_port","<- CLOSE");
+ erl_errno = (res == -2) ? ETIMEDOUT : EIO;
+ closesocket(fd);
+ return -2; /* version mismatch */
+ }
+
+ s = buf;
+ res = get8(s);
+
+ if (res != EI_EPMD_PORT2_RESP) { /* response type */
+ EI_TRACE_ERR1("ei_epmd_r4_port","<- unknown (%d)",res);
+ EI_TRACE_ERR0("ei_epmd_r4_port","-> CLOSE");
+ closesocket(fd);
+ erl_errno = EIO;
+ return -1;
+ }
+
+
+
+ /* got negative response */
+ if ((res = get8(s))) {
+ /* got negative response */
+ EI_TRACE_ERR1("ei_epmd_r4_port","<- PORT2_RESP result=%d (failure)",res);
+ closesocket(fd);
+ erl_errno = EIO;
+ return -1;
+ }
+
+ EI_TRACE_CONN1("ei_epmd_r4_port","<- PORT2_RESP result=%d (ok)",res);
+
+ /* expecting remaining 8 bytes */
+ if ((res = ei_read_fill_t(fd,buf,8,ms)) != 8) {
+ EI_TRACE_ERR0("ei_epmd_r4_port","<- CLOSE");
+ erl_errno = (res == -2) ? ETIMEDOUT : EIO;
+ closesocket(fd);
+ return -1;
+ }
+
+ closesocket(fd);
+ s = buf;
+
+ port = get16be(s);
+ ntype = get8(s);
+ proto = get8(s);
+ dist_high = get16be(s);
+ dist_low = get16be(s);
+
+ EI_TRACE_CONN5("ei_epmd_r4_port",
+ " port=%d ntype=%d proto=%d dist-high=%d dist-low=%d",
+ port,ntype,proto,dist_high,dist_low);
+
+ /* right network protocol? */
+ if (EI_MYPROTO != proto)
+ {
+ erl_errno = EIO;
+ return -1;
+ }
+
+ /* is there overlap in our distribution versions? */
+ if ((EI_DIST_HIGH < dist_low) || (EI_DIST_LOW > dist_high))
+ {
+ erl_errno = EIO;
+ return -1;
+ }
+
+ /* choose the highest common version */
+ /* i.e. min(his-max, my-max) */
+ *dist = (dist_high > EI_DIST_HIGH ? EI_DIST_HIGH : dist_high);
+
+ /* ignore the remaining fields */
+ return port;
+}
+
+/* lookup the port number of the given node. 'dist' is an out-argument
+ * which, if the lookup is successful, will be initialized to contain
+ * the highest distribution version that is common to the calling node
+ * and the node looked up. The function will attempt to contact epmd
+ * version 4 before trying version 3. R3 (and earlier) nodes have
+ * dist=0.
+ */
+int ei_epmd_port (struct in_addr *addr, const char *alive, int *dist)
+{
+ return ei_epmd_port_tmo (addr, alive, dist, 0);
+}
+
+int ei_epmd_port_tmo (struct in_addr *addr, const char *alive, int *dist,
+ unsigned ms)
+{
+ int i;
+
+ /* try the new one first, then the old one */
+ i = ei_epmd_r4_port(addr,alive,dist,ms);
+
+ /* -2: new protocol not understood */
+ if (i == -2) {
+ *dist = 0;
+ i = ei_epmd_r3_port(addr,alive,ms);
+ }
+
+ return i;
+}
+
diff --git a/lib/erl_interface/src/epmd/epmd_publish.c b/lib/erl_interface/src/epmd/epmd_publish.c
new file mode 100644
index 0000000000..09b3dce43b
--- /dev/null
+++ b/lib/erl_interface/src/epmd/epmd_publish.c
@@ -0,0 +1,228 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#include "eidef.h"
+
+#ifdef __WIN32__
+#include <winsock2.h>
+#include <windows.h>
+#include <winbase.h>
+
+#elif VXWORKS
+#include <vxWorks.h>
+#include <ifLib.h>
+#include <sockLib.h>
+#include <inetLib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#else
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "ei_internal.h"
+#include "putget.h"
+#include "ei_epmd.h"
+#include "ei_portio.h"
+
+
+/* publish our listen port and alive name */
+/* return the (useless) creation number */
+static int ei_epmd_r3_publish (int port, const char *alive, unsigned ms)
+{
+ char buf[EPMDBUF];
+ char *s = buf;
+ int fd;
+ int len = strlen(alive) + 3;
+ int res,creation;
+
+ s = buf;
+ put16be(s,len);
+ put8(s,EI_EPMD_ALIVE_REQ);
+ put16be(s,port);
+ strcpy(s, alive);
+
+ if ((fd = ei_epmd_connect_tmo(NULL,ms)) < 0) return fd;
+
+ if ((res = ei_write_fill_t(fd, buf, len+2, ms)) != len+2) {
+ closesocket(fd);
+ erl_errno = (res == -2) ? ETIMEDOUT : EIO;
+ return -1;
+ }
+
+ EI_TRACE_CONN2("ei_epmd_r3_publish",
+ "-> ALIVE_REQ alive=%s port=%d",alive,port);
+
+ if ((res = ei_read_fill_t(fd, buf, 3, ms)) != 3) {
+ closesocket(fd);
+ erl_errno = (res == -2) ? ETIMEDOUT : EIO;
+ return -1;
+ }
+
+ s = buf;
+ if ((res=get8(s)) != EI_EPMD_ALIVE_OK_RESP) {
+ EI_TRACE_ERR1("ei_epmd_r3_publish",
+ "<- ALIVE_NOK result=%d (failure)",res);
+ closesocket(fd);
+ erl_errno = EIO;
+ return -1;
+ }
+
+ creation = get16be(s);
+
+ EI_TRACE_CONN1("ei_epmd_r3_publish","<- ALIVE_OK creation=%d",creation);
+
+ /* Don't close fd here! It keeps us registered with epmd */
+
+ /* probably should save fd so we can close it later... */
+ /* epmd_saveconn(OPEN,fd,alive); */
+
+ /* return the creation number, for no good reason */
+ /* return creation; */
+
+ /* no! return the descriptor */
+ return fd;
+}
+
+/* publish our listen port and alive name */
+/* return the (useless) creation number */
+/* this protocol is a lot more complex than the old one */
+static int ei_epmd_r4_publish (int port, const char *alive, unsigned ms)
+{
+ char buf[EPMDBUF];
+ char *s = buf;
+ int fd;
+ int elen = 0;
+ int nlen = strlen(alive);
+ int len = elen + nlen + 13; /* hard coded: be careful! */
+ int n;
+ int res, creation;
+
+ s = buf;
+ put16be(s,len);
+
+ put8(s,EI_EPMD_ALIVE2_REQ);
+ put16be(s,port); /* port number */
+ put8(s,'h'); /* h = r4 hidden node */
+ put8(s, EI_MYPROTO); /* protocol 0 ?? */
+ put16be(s,EI_DIST_HIGH); /* highest understood version: 1 = R4 */
+ put16be(s,EI_DIST_LOW); /* lowest: 0 = R3 */
+ put16be(s,nlen); /* length of alivename */
+ strcpy(s, alive);
+ s += nlen;
+ put16be(s,elen); /* length of extra string = 0 */
+ /* no extra string */
+
+ if ((fd = ei_epmd_connect_tmo(NULL,ms)) < 0) return fd;
+
+ if ((res = ei_write_fill_t(fd, buf, len+2, ms)) != len+2) {
+ closesocket(fd);
+ erl_errno = (res == -2) ? ETIMEDOUT : EIO;
+ return -1;
+ }
+
+ EI_TRACE_CONN6("ei_epmd_r4_publish",
+ "-> ALIVE2_REQ alive=%s port=%d ntype=%d "
+ "proto=%d dist-high=%d dist-low=%d",
+ alive,port,'H',EI_MYPROTO,EI_DIST_HIGH,EI_DIST_LOW);
+
+ if ((n = ei_read_fill_t(fd, buf, 4, ms)) != 4) {
+ EI_TRACE_ERR0("ei_epmd_r4_publish","<- CLOSE");
+ closesocket(fd);
+ erl_errno = (n == -2) ? ETIMEDOUT : EIO;
+ return -2; /* version mismatch */
+ }
+ /* Don't close fd here! It keeps us registered with epmd */
+ s = buf;
+ if (((res=get8(s)) != EI_EPMD_ALIVE2_RESP)) { /* response */
+ EI_TRACE_ERR1("ei_epmd_r4_publish","<- unknown (%d)",res);
+ EI_TRACE_ERR0("ei_epmd_r4_publish","-> CLOSE");
+ closesocket(fd);
+ erl_errno = EIO;
+ return -1;
+ }
+
+ EI_TRACE_CONN0("ei_epmd_r4_publish","<- ALIVE2_RESP");
+
+ if (((res=get8(s)) != 0)) { /* 0 == success */
+ EI_TRACE_ERR1("ei_epmd_r4_publish"," result=%d (fail)",res);
+ closesocket(fd);
+ erl_errno = EIO;
+ return -1;
+ }
+
+ creation = get16be(s);
+
+ EI_TRACE_CONN2("ei_epmd_r4_publish",
+ " result=%d (ok) creation=%d",res,creation);
+
+ /* probably should save fd so we can close it later... */
+ /* epmd_saveconn(OPEN,fd,alive); */
+
+ /* return the creation number, for no good reason */
+ /* return creation;*/
+
+ /* no - return the descriptor */
+ return fd;
+}
+
+int ei_epmd_publish(int port, const char *alive)
+{
+ return ei_epmd_publish_tmo(port, alive, 0);
+}
+
+int ei_epmd_publish_tmo(int port, const char *alive, unsigned ms)
+{
+ int i;
+
+ /* try the new one first, then the old one */
+ i = ei_epmd_r4_publish(port,alive, ms);
+
+ /* -2: new protocol not understood */
+ if (i == -2) i = ei_epmd_r3_publish(port,alive, ms);
+
+ return i;
+}
+
+
+/*
+ * Publish a name for our C-node.
+ * a file descriptor is returned - close it to unpublish.
+ *
+ */
+int ei_publish(ei_cnode* ec, int port)
+{
+ return ei_epmd_publish(port, ei_thisalivename(ec));
+}
+
+int ei_publish_tmo(ei_cnode* ec, int port, unsigned ms)
+{
+ return ei_epmd_publish_tmo(port, ei_thisalivename(ec), ms);
+}
diff --git a/lib/erl_interface/src/epmd/epmd_unpublish.c b/lib/erl_interface/src/epmd/epmd_unpublish.c
new file mode 100644
index 0000000000..08662fe1ec
--- /dev/null
+++ b/lib/erl_interface/src/epmd/epmd_unpublish.c
@@ -0,0 +1,106 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+#ifdef __WIN32__
+#include <winsock2.h>
+#include <windows.h>
+#include <winbase.h>
+
+#elif VXWORKS
+#include <vxWorks.h>
+#include <ifLib.h>
+#include <sockLib.h>
+#include <inetLib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#else
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "eidef.h"
+#include "ei_internal.h"
+#include "putget.h"
+#include "ei_epmd.h"
+#include "ei_portio.h"
+
+
+/* stop the specified node */
+int ei_unpublish_tmo(const char *alive, unsigned ms)
+{
+ char buf[EPMDBUF];
+ char *s = (char*)buf;
+ int len = 1 + strlen(alive);
+ int fd, res;
+
+ put16be(s,len);
+ put8(s,EI_EPMD_STOP_REQ);
+ strcpy(s, alive);
+
+ /* FIXME can't connect, return success?! At least commen whats up */
+ if ((fd = ei_epmd_connect_tmo(NULL,ms)) < 0) return fd;
+
+ if ((res = ei_write_fill_t(fd, buf, len+2,ms)) != len+2) {
+ closesocket(fd);
+ erl_errno = (res == -2) ? ETIMEDOUT : EIO;
+ return -1;
+ }
+
+ EI_TRACE_CONN1("ei_unpublish_tmo","-> STOP %s",alive);
+
+ if ((res = ei_read_fill_t(fd, buf, 7, ms)) != 7) {
+ closesocket(fd);
+ erl_errno = (res == -2) ? ETIMEDOUT : EIO;
+ return -1;
+ }
+ closesocket(fd);
+ buf[7]=(char)0; /* terminate the string */
+
+ if (!strcmp("STOPPED",(char *)buf)) {
+ EI_TRACE_CONN0("ei_unpublish_tmo","<- STOPPED (success)");
+ return 0;
+ }
+ else if (!strcmp("NOEXIST",(char *)buf)) {
+ EI_TRACE_ERR0("ei_unpublish_tmo","<- NOEXIST (failure)");
+ erl_errno = EIO;
+ return -1;
+ }
+ else {
+ EI_TRACE_ERR0("ei_unpublish_tmo","<- unknown (failure)");
+ erl_errno = EIO;
+ return -1; /* this shouldn't happen */
+ }
+ return 0;
+}
+
+
+int ei_unpublish(ei_cnode* ec)
+{
+ return ei_unpublish_tmo(ei_thisalivename(ec),0);
+}