Exemple #1
0
 /* ip_addr is now in network byte order 
  *
  * first we have to get hold of the portnumber to
  *  the node through epmd at that host 
  *
*/
int ei_xconnect_tmo(ei_cnode* ec, Erl_IpAddr adr, char *alivename, unsigned ms)
{
    struct in_addr *ip_addr=(struct in_addr *) adr;
    int rport = 0; /*uint16 rport = 0;*/
    int sockd;
    int one = 1;
    int dist = 0;
    ErlConnect her_name;
    unsigned her_flags, her_version;

    erl_errno = EIO;		/* Default error code */
    
    EI_TRACE_CONN1("ei_xconnect","-> CONNECT attempt to connect to %s",
		   alivename);
    
    if ((rport = ei_epmd_port_tmo(ip_addr,alivename,&dist, ms)) < 0) {
	EI_TRACE_ERR0("ei_xconnect","-> CONNECT can't get remote port");
	/* ei_epmd_port_tmo() has set erl_errno */
	return ERL_NO_PORT;
    }
    
    /* we now have port number to enode, try to connect */
    if((sockd = cnct((uint16)rport, ip_addr, sizeof(struct in_addr),ms)) < 0) {
	EI_TRACE_ERR0("ei_xconnect","-> CONNECT socket connect failed");
	/* cnct() has set erl_errno */
	return ERL_CONNECT_FAIL;
    }
    
    EI_TRACE_CONN0("ei_xconnect","-> CONNECT connected to remote");

    /* FIXME why connect before checking 'dist' output from ei_epmd_port() ?! */
    if (dist <= 4) {
	EI_TRACE_ERR0("ei_xconnect","-> CONNECT remote version not compatible");
	goto error;
    }
    else {
	unsigned our_challenge, her_challenge;
	unsigned char our_digest[16];
	
	if (send_name(sockd, ec->thisnodename, (unsigned) dist, ms))
	    goto error;
	if (recv_status(sockd, ms))
	    goto error;
	if (recv_challenge(sockd, &her_challenge, &her_version,
	    &her_flags, &her_name, ms))
	    goto error;
	our_challenge = gen_challenge();
	gen_digest(her_challenge, ec->ei_connect_cookie, our_digest);
	if (send_challenge_reply(sockd, our_digest, our_challenge, ms))
	    goto error;
	if (recv_challenge_ack(sockd, our_challenge, 
	    ec->ei_connect_cookie, ms))
	    goto error;
	put_ei_socket_info(sockd, dist, null_cookie, ec); /* FIXME check == 0 */
    }
    
    setsockopt(sockd, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one));
    setsockopt(sockd, SOL_SOCKET, SO_KEEPALIVE, (char *)&one, sizeof(one));

    EI_TRACE_CONN1("ei_xconnect","-> CONNECT (ok) remote = %s",alivename);
    
    erl_errno = 0;
    return sockd;
    
error:
    EI_TRACE_ERR0("ei_xconnect","-> CONNECT failed");
    closesocket(sockd);
    return ERL_ERROR;
} /* ei_xconnect */
Exemple #2
0
/* 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);
}