aboutsummaryrefslogtreecommitdiffstats
path: root/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c')
-rw-r--r--lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c224
1 files changed, 224 insertions, 0 deletions
diff --git a/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c b/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c
new file mode 100644
index 0000000000..5f898b5944
--- /dev/null
+++ b/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c
@@ -0,0 +1,224 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2001-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%
+ */
+
+/*
+ * Purpose: Tests the accept function in ei_connect.c.
+ * Author: Jakob Cederlund (taken from erl_connect by Bj�rn Gustavsson)
+ *
+ * See the ei_accept_SUITE.erl file for a "table of contents".
+ */
+
+#include <stdio.h>
+#include <string.h>
+#ifdef VXWORKS
+#include "reclaim.h"
+#endif
+
+#ifdef __WIN32__
+#include <winsock2.h>
+#include <windows.h>
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#endif
+
+#include "ei_runner.h"
+
+static void cmd_ei_connect_init(char* buf, int len);
+static void cmd_ei_accept(char* buf, int len);
+static void cmd_ei_receive(char* buf, int len);
+static void cmd_ei_unpublish(char* buf, int len);
+
+static void send_errno_result(int value);
+
+ei_cnode ec;
+
+
+static struct {
+ char* name;
+ int num_args; /* Number of arguments. */
+ void (*func)(char* buf, int len);
+} commands[] = {
+ "ei_connect_init", 3, cmd_ei_connect_init,
+ "ei_accept", 1, cmd_ei_accept,
+ "ei_receive", 1, cmd_ei_receive,
+ "ei_unpublish", 0, cmd_ei_unpublish
+};
+
+/*
+ * Sends a list contaning all data types to the Erlang side.
+ */
+TESTCASE(interpret)
+{
+ ei_x_buff x;
+ int i;
+ ei_term term;
+
+ ei_x_new(&x);
+ for (;;) {
+ if (get_bin_term(&x, &term)) {
+ report(1);
+ return;
+ } else {
+ char* buf = x.buff, func[MAXATOMLEN];
+ int index = x.index, arity;
+ if (term.ei_type != ERL_SMALL_TUPLE_EXT || term.arity != 2)
+ fail("term should be a tuple of size 2");
+ if (ei_decode_atom(buf, &index, func) < 0)
+ fail("function name should be an atom");
+ if (ei_decode_tuple_header(buf, &index, &arity) != 0)
+ fail("function arguments should be a tuple");
+ for (i = 0; i < sizeof(commands)/sizeof(commands[0]); i++) {
+ if (strcmp(func, commands[i].name) == 0) {
+ if (arity != commands[i].num_args)
+ fail("wrong number of arguments");
+ commands[i].func(buf + index, x.buffsz - index);
+ break;
+ }
+ }
+ if (i >= sizeof(commands)/sizeof(commands[0])) {
+ message("\"%d\" \n", func);
+ fail("bad command");
+ }
+ }
+ }
+}
+
+static void cmd_ei_connect_init(char* buf, int len)
+{
+ int index = 0, r = 0;
+ int type, size;
+ long l;
+ char b[100];
+ char cookie[MAXATOMLEN], * cp = cookie;
+ ei_x_buff res;
+ if (ei_decode_long(buf, &index, &l) < 0)
+ fail("expected int");
+ sprintf(b, "c%d", l);
+ /* FIXME don't use internal and maybe use skip?! */
+ ei_get_type_internal(buf, &index, &type, &size);
+ if (ei_decode_atom(buf, &index, cookie) < 0)
+ fail("expected atom (cookie)");
+ if (cookie[0] == '\0')
+ cp = NULL;
+ r = ei_connect_init(&ec, b, cp, 0);
+ ei_x_new_with_version(&res);
+ ei_x_encode_long(&res, r);
+ send_bin_term(&res);
+ ei_x_free(&res);
+}
+
+static int my_listen(int port)
+{
+ int listen_fd;
+ struct sockaddr_in addr;
+ const char *on = "1";
+
+ if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ return -1;
+
+ setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, on, sizeof(on));
+
+ memset((void*) &addr, 0, (size_t) sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+
+ if (bind(listen_fd, (struct sockaddr*) &addr, sizeof(addr)) < 0)
+ return -1;
+
+ listen(listen_fd, 5);
+ return listen_fd;
+}
+
+static void cmd_ei_accept(char* buf, int len)
+{
+ int index = 0;
+ int listen, r;
+ ErlConnect conn;
+ long port;
+ ei_x_buff x;
+ int i;
+
+ /* get port */
+ if (ei_decode_long(buf, &index, &port) < 0)
+ fail("expected int (port)");
+ /* Make a listen socket */
+ if ((listen = my_listen(port)) <= 0)
+ fail("listen");
+
+ if ((i = ei_publish(&ec, port)) == -1)
+ fail("ei_publish");
+#ifdef VXWORKS
+ save_fd(i);
+#endif
+ r = ei_accept(&ec, listen, &conn);
+#ifdef VXWORKS
+ save_fd(r);
+#endif
+ /* send result, errno and nodename */
+ ei_x_new_with_version(&x);
+ ei_x_encode_tuple_header(&x, 3);
+ ei_x_encode_long(&x, r);
+ ei_x_encode_long(&x, erl_errno);
+ ei_x_encode_atom(&x, conn.nodename); /* or rather string? */
+ send_bin_term(&x);
+ ei_x_free(&x);
+}
+
+static void cmd_ei_receive(char* buf, int len)
+{
+ ei_x_buff x;
+ erlang_msg msg;
+ long l;
+ int fd, index = 0;
+
+ if (ei_decode_long(buf, &index, &l) < 0)
+ fail("expected int (fd)");
+ fd = l;
+ ei_x_new(&x);
+ for (;;) {
+ int got = ei_xreceive_msg(fd, &msg, &x);
+ if (got == ERL_TICK)
+ continue;
+ if (got == ERL_ERROR)
+ fail("ei_xreceive_msg");
+ break;
+ }
+ index = 1;
+ send_bin_term(&x);
+ ei_x_free(&x);
+}
+
+static void cmd_ei_unpublish(char* buf, int len)
+{
+ send_errno_result(ei_unpublish(&ec));
+}
+
+static void send_errno_result(int value)
+{
+ ei_x_buff x;
+ ei_x_new_with_version(&x);
+ ei_x_encode_tuple_header(&x, 2);
+ ei_x_encode_long(&x, value);
+ ei_x_encode_long(&x, erl_errno);
+ send_bin_term(&x);
+ ei_x_free(&x);
+}