Esempio n. 1
0
int start_cnode(const char *cookie_file, ei_cnode *ec, int *epmd_sock, int *listen_sock, const char *reg_name, const char *host_name) {
	char *cookie = 0, *default_node_name = 0, *node_name;
	short creation = 0;
	int s, port, pub, tries;
	socklen_t addr_len;
	struct sockaddr_in addr;

	cookie = read_cookie(cookie_file);
	node_name = (char *)malloc(strlen(reg_name) + strlen(host_name) + 2);
	strcpy(node_name, reg_name);
	strcat(node_name, "@");
	strcat(node_name, host_name);
	/* The thisipaddr parameter is unused at the moment (R13B01). */
	ei_connect_xinit(ec, host_name, reg_name, node_name, 0, cookie, creation);

	if (cookie)
		free(cookie);
	if (default_node_name)
		free(default_node_name);
	free(node_name);

	s = open_port();
	addr_len = sizeof addr;
	getsockname(s, (struct sockaddr *)&addr, &addr_len);
	port = ntohs(addr.sin_port);
	DEBUG_V("bound port %d", port);

	/* It's possible that epmd has been started, but hasn't yet finished starting
	 * up, so we have a few goes at connecting. Like erl, epmd goes directly into
	 * the background when started, not indicating when it's ready. */
	DEBUG("connecting to epmd");
	tries = 0;
	while (1) {
		pub = ei_publish(ec, port);
		if (pub != -1)
			break;
		if (!tries)
			fprintf(stderr, "Waiting for connection to epmd.\n");
		if (tries++ < ERLD_MAX_TRIES) {
			if (debug_flag)
				erl_err_ret("epmd connection failed, polling (attempt %d/%d)", tries, ERLD_MAX_TRIES);
			usleep(ERLD_POLL_TIME * 1000);
		}
		else {
			erl_err_ret("Unable to connect to epmd");
			return -1;
		}
	}
	*epmd_sock = pub;
	*listen_sock = s;
	return 0;
}
Esempio n. 2
0
/* Return values:
 * - -1 error
 * - 0 nothing
 * - 1 detach */
int cnode_read(int fd, char **ret_str) {
    ei_x_buff x;
    erlang_msg msg;
    int result, index, o_index, arity, type, size, ver, rv = CNODE_IGNORE;
    const char *str;
    char *s;
    char atom[MAXATOMLEN];

    ei_x_new(&x);
    /* We don't use xreceive because we're not expecting any big
       messages and we don't want a huge term to cause our memory
       usage to blow out and crash us. */
    /* Use a timeout of 1 millisecond even though we know we'll
       be able to read at least some bytes, just to be sure we
       do not get blocked (for long). Really we want to specify
       "no timeout but don't block" to ei_receive_msg but it
       doesn't provide that functionality. */
    result = ei_receive_msg_tmo(fd, &msg, &x, 1);

    if (result < 0) {
        if (debug_flag)
            erl_err_ret("ei_receive_msg_tmo failed");
        switch (erl_errno) {
        case ETIMEDOUT:
            DEBUG("ei_receive_msg_tmo: timed out.");
            break;
        case EAGAIN:
            DEBUG("ei_receive_msg_tmo: try again");
            break;
        case EMSGSIZE:
            DEBUG("ei_receive_msg_tmo: message too big");
            rv = CNODE_ERROR;
            break;
        case EIO:
            DEBUG_V("ei_receive_msg_tmo: IO error (%d: %s)", errno, strerror(errno));
            if (errno != EAGAIN)
                rv = CNODE_ERROR;
            break;
        }
    }
    else {
        if (result == ERL_TICK) { /* nothing to do */
            DEBUG("node tick message");
        }
        else {
            switch (msg.msgtype) {
            case ERL_SEND:
                str = "SEND";
                break;
            case ERL_REG_SEND:
                str = "REG_SEND";
                break;
            case ERL_LINK:
                str = "LINK";
                break;
            case ERL_UNLINK:
                str = "UNLINK";
                break;
            default:
                str = "unknown";
            }
            if (msg.msgtype == ERL_REG_SEND) {
                index = 0;

                if (ei_decode_version(x.buff, &index, &ver) == 0) {
                    // DEBUG_V("data ver %d", ver);
                }

                o_index = index;

                if (ei_decode_atom(x.buff, &index, atom) == 0) {
                    // DEBUG_V("atom %s", atom);
                    if (!strcmp(atom, "detach")) {
                        DEBUG("got detach message");
                        rv = CNODE_DETACH;
                    }
                    else if (!strcmp(atom, "thump")) {
                        rv = CNODE_THUMP;
                    }
                    else {
                        DEBUG("message is unknown");
                    }
                }
                else if (ei_decode_tuple_header(x.buff, &index, &arity) == 0) {
                    if ((arity == 2)
                            && !ei_decode_atom(x.buff, &index, atom) && !strcmp(atom, "stdout")
                            && !ei_get_type(x.buff, &index, &type, &size)
                            && (type == ERL_STRING_EXT)) {
                        *ret_str = (char *)malloc(size + 1);
                        if (ei_decode_string(x.buff, &index, *ret_str)) {
                            LOG("Failed to decode string for stdout message.");
                            free(*ret_str);
                            rv = CNODE_ERROR;
                        }
                        else
                            rv = CNODE_STR;
                    }
                    else {
                        index = o_index; // Re-set index to beginning of term.
                        s = 0;
                        ei_s_print_term(&s, x.buff, &index);
                        LOG_V("Unknown tuple (arity %d): %s", arity, s);
                        free(s);
                    }
                }
                else {
                    s = 0;
                    ei_s_print_term(&s, x.buff, &index);
                    LOG_V("Unknown message: %s", s);
                    free(s);
                }
            }
            else {
                DEBUG_V("received %s message", str);
            }
        }
    }
    ei_x_free(&x);
    return rv;
}
Esempio n. 3
0
int main(void)
#endif
{
  ei_x_buff eix;
  int index = 0;
  ETERM **etermpp = NULL, *etermp = NULL;
  char *charp = NULL;
  unsigned char uchar, **ucharpp = NULL, *ucharp = NULL;
  void *voidp = NULL;
  Erl_Heap *erl_heapp = NULL;
  int intx = 0;
  int *intp = NULL;
  unsigned int uintx, *uintp;
  unsigned long *ulongp = NULL;
  long longx = 0;
  double doublex = 0.0;
  short shortx = 42;
  FILE *filep = NULL;
  Erl_IpAddr erl_ipaddr = NULL;
  ErlMessage *erlmessagep = NULL;
  ErlConnect *erlconnectp = NULL;
  struct hostent *hostp = NULL;
  struct in_addr *inaddrp = NULL;

  /* Converion to erl_interface format is in liberl_interface */

  intx = erl_errno;

  ei_encode_term(charp, &index, voidp);
  ei_x_encode_term(&eix, voidp);
  ei_decode_term(charp, &index, voidp);

  erl_init(voidp, longx);
  erl_connect_init(intx, charp,shortx);
  erl_connect_xinit(charp,charp,charp,erl_ipaddr,charp,shortx);
  erl_connect(charp); 
  erl_xconnect(erl_ipaddr,charp);
  erl_close_connection(intx);
  erl_receive(intx, ucharp, intx);
  erl_receive_msg(intx, ucharp, intx, erlmessagep);
  erl_xreceive_msg(intx, ucharpp, intp, erlmessagep);
  erl_send(intx, etermp, etermp);
  erl_reg_send(intx, charp, etermp);
  erl_rpc(intx,charp,charp,etermp);
  erl_rpc_to(intx,charp,charp,etermp);
  erl_rpc_from(intx,intx,erlmessagep);

  erl_publish(intx);
  erl_accept(intx,erlconnectp);

  erl_thiscookie();
  erl_thisnodename();
  erl_thishostname();
  erl_thisalivename();
  erl_thiscreation();
  erl_unpublish(charp);
  erl_err_msg(charp);
  erl_err_quit(charp);
  erl_err_ret(charp);
  erl_err_sys(charp);

  erl_cons(etermp,etermp);
  erl_copy_term(etermp);
  erl_element(intx,etermp);

  erl_hd(etermp);
  erl_iolist_to_binary(etermp);
  erl_iolist_to_string(etermp);
  erl_iolist_length(etermp);
  erl_length(etermp);
  erl_mk_atom(charp);
  erl_mk_binary(charp,intx);
  erl_mk_empty_list();
  erl_mk_estring(charp, intx);
  erl_mk_float(doublex);
  erl_mk_int(intx);
  erl_mk_list(etermpp,intx);
  erl_mk_pid(charp,uintx,uintx,uchar);
  erl_mk_port(charp,uintx,uchar);
  erl_mk_ref(charp,uintx,uchar);
  erl_mk_long_ref(charp,uintx,uintx,uintx,uchar);
  erl_mk_string(charp);
  erl_mk_tuple(etermpp,intx);
  erl_mk_uint(uintx);
  erl_mk_var(charp);
  erl_print_term(filep,etermp);
  /*  erl_sprint_term(charp,etermp); */
  erl_size(etermp);
  erl_tl(etermp);
  erl_var_content(etermp, charp);

  erl_format(charp);
  erl_match(etermp, etermp);

  erl_global_names(intx, intp);
  erl_global_register(intx, charp, etermp);
  erl_global_unregister(intx, charp);
  erl_global_whereis(intx, charp, charp);

  erl_init_malloc(erl_heapp,longx);
  erl_alloc_eterm(uchar);
  erl_eterm_release();
  erl_eterm_statistics(ulongp,ulongp);
  erl_free_array(etermpp,intx);
  erl_free_term(etermp);
  erl_free_compound(etermp);
  erl_malloc(longx);
  erl_free(voidp);

  erl_compare_ext(ucharp, ucharp);
  erl_decode(ucharp);
  erl_decode_buf(ucharpp);
  erl_encode(etermp,ucharp);
  erl_encode_buf(etermp,ucharpp);
  erl_ext_size(ucharp);
  erl_ext_type(ucharp);
  erl_peek_ext(ucharp,intx);
  erl_term_len(etermp);

  erl_gethostbyname(charp);
  erl_gethostbyaddr(charp, intx, intx);
  erl_gethostbyname_r(charp, hostp, charp, intx, intp);
  erl_gethostbyaddr_r(charp, intx, intx, hostp, charp, intx, intp);

  erl_init_resolve();
  erl_distversion(intx);

  erl_epmd_connect(inaddrp);
  erl_epmd_port(inaddrp, charp, intp);

  charp  = ERL_ATOM_PTR(etermp);
  intx   = ERL_ATOM_SIZE(etermp);
  ucharp = ERL_BIN_PTR(etermp);
  intx   = ERL_BIN_SIZE(etermp);
  etermp = ERL_CONS_HEAD(etermp);
  etermp = ERL_CONS_TAIL(etermp);
  intx   = ERL_COUNT(etermp);
  doublex= ERL_FLOAT_VALUE(etermp);
  uintx  = ERL_INT_UVALUE(etermp);
  intx   = ERL_INT_VALUE(etermp);
  intx   = ERL_IS_ATOM(etermp);
  intx   = ERL_IS_BINARY(etermp);
  intx   = ERL_IS_CONS(etermp);
  intx   = ERL_IS_EMPTY_LIST(etermp);
  intx   = ERL_IS_FLOAT(etermp);
  intx   = ERL_IS_INTEGER(etermp);
  intx   = ERL_IS_LIST(etermp);
  intx   = ERL_IS_PID(etermp);
  intx   = ERL_IS_PORT(etermp);
  intx   = ERL_IS_REF(etermp);
  intx   = ERL_IS_TUPLE(etermp);
  intx   = ERL_IS_UNSIGNED_INTEGER(etermp);
  uchar  = ERL_PID_CREATION(etermp);
  charp  = ERL_PID_NODE(etermp);
  uintx  = ERL_PID_NUMBER(etermp);
  uintx  = ERL_PID_SERIAL(etermp);
  uchar  = ERL_PORT_CREATION(etermp);
  charp  = ERL_PORT_NODE(etermp);
  uintx  = ERL_PORT_NUMBER(etermp);
  uchar  = ERL_REF_CREATION(etermp);
  intx   = ERL_REF_LEN(etermp);
  charp  = ERL_REF_NODE(etermp);
  uintx  = ERL_REF_NUMBER(etermp);
  uintp  = ERL_REF_NUMBERS(etermp);
  etermp = ERL_TUPLE_ELEMENT(etermp,intx);
  intx   = ERL_TUPLE_SIZE(etermp);

  return 
      BUFSIZ +
      EAGAIN +
      EHOSTUNREACH +
      EINVAL +
      EIO +
      EMSGSIZE +
      ENOMEM +
      ERL_ATOM +
      ERL_BINARY +
      ERL_ERROR +
      ERL_EXIT +
      ERL_FLOAT +
      ERL_INTEGER +
      ERL_LINK +
      ERL_LIST +
      ERL_MSG +
      ERL_NO_TIMEOUT +
      ERL_PID +
      ERL_PORT +
      ERL_REF +
      ERL_REG_SEND +
      ERL_SEND +
      ERL_SMALL_BIG +
      ERL_TICK +
      ERL_TIMEOUT +
      ERL_TUPLE +
      ERL_UNLINK +
      ERL_U_INTEGER +
      ERL_U_SMALL_BIG +
      ERL_VARIABLE +
      ETIMEDOUT +
      MAXNODELEN +
      MAXREGLEN;
}
Esempio n. 4
0
void process_init_cmd(ETERM* init_cmd_pattern, int erl_fd, ETERM* msg_frompid)
{
    fprintf(stderr, "process_init_cmd got PID "); erl_print_term(stderr, msg_frompid); fprintf(stderr, "\n");

    ETERM* response;
    ETERM* msg_arg = erl_var_content(init_cmd_pattern, "Arg");

    if (!ERL_IS_LIST(msg_arg))
    {
        erl_err_msg("invalid argument to init command");
        response = erl_format("{ecap_node, {error, {badarg, {init, ~w} } } }", msg_arg);
        erl_send(erl_fd, msg_frompid, response);
        goto invarg_cleanup;
    }

    char* fn_str = erl_iolist_to_string(msg_arg);
    if (fn_str == NULL)
    {
        erl_err_msg("could not unpack string");
        response = erl_format("{ecap_node, {error, {badarg, {init, ~w}}}}", msg_arg);
        erl_send(erl_fd, msg_frompid, response);
        goto nostr_cleanup;
    }
    TRACE(("init command got argstring: %s", fn_str));

    pthread_t* thread = (pthread_t*)malloc(sizeof(pthread_t));
    info_t* threadinfo = (info_t*)malloc(sizeof(info_t));

    // We copy all of this data because the transient pointers will be free()d
    //  just before each function returns, destroying in the thread context.
    threadinfo->topid = msg_frompid;
    threadinfo->self  = thread;
    threadinfo->fname = (char*)malloc(strlen(fn_str)+1);
    strncpy(threadinfo->fname, fn_str, strlen(fn_str)+1);
    threadinfo->erlvm_fd = erl_fd;

    int ret;
    if ((ret = pthread_create(thread, NULL, watcher, threadinfo)) != 0)
    {
        TRACE(("failed to create thread, with return code %d", ret));
        erl_err_ret("failed to create watcher thread");
        response = erl_format("{ecap_node, {error, {threadfail}}}");
        erl_send(erl_fd, msg_frompid, response);
        TRACE(("freeing thread stuff"));
        free(thread);
        free(threadinfo->fname);
        free(threadinfo);
        goto nothread_cleanup;
    }

    response = erl_format("{ecap_node, ok}");
    erl_send(erl_fd, msg_frompid, response);

    TRACE(("normal cleanup from init command call"));
nothread_cleanup:
nostr_cleanup:
    TRACE(("freeing fn_str"));
    erl_free(fn_str);
invarg_cleanup:
    TRACE(("freeing terms"));
    erl_free_term(response);
    erl_free_term(msg_arg);
    TRACE(("done with init command processing"));
}