示例#1
0
static int send_challenge_ack(int fd, unsigned char digest[16], unsigned ms) 
{
    char *s;
    char buf[DEFBUF_SIZ];
    int siz = 2 + 1 + 16;
    int res;

    s = buf;
    
    put16be(s,siz - 2);
    put8(s, 'a');
    memcpy(s, digest, 16);

    if ((res = ei_write_fill_t(fd, buf, siz, ms)) != siz) {
	EI_TRACE_ERR0("recv_challenge_reply",
		      "-> SEND_CHALLENGE_ACK socket write failed");
	erl_errno = (res == -2) ? ETIMEDOUT : EIO;
	return -1;
    }
    
    if (ei_tracelevel >= 3) {
	char buffer[33];	
    	EI_TRACE_CONN1("recv_challenge_reply",
		   "-> SEND_CHALLENGE_ACK (ok) digest = %s",hex((char *)digest,buffer));
    }
    
    return 0;
}
示例#2
0
/* Receives a message from an Erlang socket.
 * If the message was a TICK it is immediately
 * answered. Returns: ERL_ERROR, ERL_TICK or
 * the number of bytes read.
 */
int ei_receive_tmo(int fd, unsigned char *bufp, int bufsize, unsigned ms) 
{
    int len;
    unsigned char fourbyte[4]={0,0,0,0};
    int res;
 
    if ((res = ei_read_fill_t(fd, (char *) bufp, 4, ms))  != 4) {
	erl_errno = (res == -2) ? ETIMEDOUT : EIO;
	return ERL_ERROR;
    }
    
    /* Tick handling */
    if ((len = get_int32(bufp)) == ERL_TICK) 
    {
	ei_write_fill_t(fd, (char *) fourbyte, 4, ms);
	/* FIXME ok to ignore error or timeout? */
	erl_errno = EAGAIN;
	return ERL_TICK;
    }
    else if (len > bufsize) 
    {
	/* FIXME: We should drain the message. */
	erl_errno = EMSGSIZE;
	return ERL_ERROR;
    }
    else if ((res = ei_read_fill_t(fd, (char *) bufp, len, ms)) != len)
    {
	erl_errno = (res == -2) ? ETIMEDOUT : EIO;
	return ERL_ERROR;
    }
    
    return len;
    
}
示例#3
0
/* this sends either link or unlink ('which' decides) */
static int link_unlink(int fd, const erlang_pid *from, const erlang_pid *to,
		       int which, unsigned ms)
{
  char msgbuf[EISMALLBUF];
  char *s;
  int index = 0;
  int n;

  index = 5;                                     /* max sizes: */
  ei_encode_version(msgbuf,&index);                     /*   1 */
  ei_encode_tuple_header(msgbuf,&index,3);
  ei_encode_long(msgbuf,&index,which);
  ei_encode_pid(msgbuf,&index,from);                    /* 268 */
  ei_encode_pid(msgbuf,&index,to);                      /* 268 */

  /* 5 byte header missing */
  s = msgbuf;
  put32be(s, index - 4);                                /*   4 */
  put8(s, ERL_PASS_THROUGH);                            /*   1 */
                                                  /* sum:  542 */


#ifdef DEBUG_DIST
  if (ei_trace_distribution > 1) ei_show_sendmsg(stderr,msgbuf,NULL);
#endif

  n = ei_write_fill_t(fd,msgbuf,index,ms); 

  return (n==index ? 0 : -1);
}
示例#4
0
static int send_status(int fd, char *status, unsigned ms)
{
    char *buf, *s;
    char dbuf[DEFBUF_SIZ];
    int siz = strlen(status) + 1 + 2;
    int res;

    buf = (siz > DEFBUF_SIZ) ? malloc(siz) : dbuf;
    if (!buf) {
	erl_errno = ENOMEM;
	return -1;
    }
    s = buf;
    put16be(s,siz - 2);
    put8(s, 's');
    memcpy(s, status, strlen(status));
    if ((res = ei_write_fill_t(fd, buf, siz, ms)) != siz) {
	EI_TRACE_ERR0("send_status","-> SEND_STATUS socket write failed");
	if (buf != dbuf)
	    free(buf);
	erl_errno = (res == -2) ? ETIMEDOUT : EIO;
	return -1;
    }
    EI_TRACE_CONN1("send_status","-> SEND_STATUS (%s)",status);

    if (buf != dbuf)
	free(buf);
    return 0;
}
示例#5
0
文件: send_exit.c 项目: AlainODea/otp
int ei_send_exit_tmo(int fd, const erlang_pid *from, const erlang_pid *to,
		     const char *reason, unsigned ms)
{
  char sbuf[EISMALLBUF];
  erlang_trace *token = NULL;
  char *dbuf = NULL;
  char *msgbuf;
  char *s;
  int index = 0;
  int len = strlen(reason) + 1080; /* see below */

  if (len > EISMALLBUF)
    if (!(dbuf = malloc(len)))
      return -1;
  msgbuf = (dbuf ? dbuf : sbuf);


  /* are we tracing? */
  /* check that he can receive trace tokens first */
  if (ei_distversion(fd) > 0) token = ei_trace(0,NULL);

  index = 5;                                     /* max sizes: */
  ei_encode_version(msgbuf,&index);                     /*   1 */
  if (token) {
    ei_encode_tuple_header(msgbuf,&index,5);            /*   2 */
    ei_encode_long(msgbuf,&index,ERL_EXIT_TT);          /*   2 */
  }
  else {
    ei_encode_tuple_header(msgbuf,&index,4);
    ei_encode_long(msgbuf,&index,ERL_EXIT);
  }
  ei_encode_pid(msgbuf,&index,from);                    /* 268 */
  ei_encode_pid(msgbuf,&index,to);                      /* 268 */

  if (token) ei_encode_trace(msgbuf,&index,token);      /* 534 */

  /* Reason */
  ei_encode_string(msgbuf,&index,reason);               /* len */

  /* 5 byte header missing */
  s = msgbuf;
  put32be(s, index - 4);                                /*   4 */
  put8(s, ERL_PASS_THROUGH);                                /*   1 */
                                          /*** sum: len + 1080 */
  /* FIXME incorrect level */
  if (ei_tracelevel > 1)
      ei_show_sendmsg(stderr,msgbuf,NULL);

  ei_write_fill_t(fd,msgbuf,index,ms); 
  /* FIXME ignore timeout etc? erl_errno?! */

  if (dbuf) free(dbuf);
  return 0;
}
示例#6
0
static int send_name_or_challenge(int fd, char *nodename,
				  int f_chall,
				  unsigned challenge,
				  unsigned version,
				  unsigned ms) 
{
    char *buf;
    unsigned char *s;
    char dbuf[DEFBUF_SIZ];
    int siz = 2 + 1 + 2 + 4 + strlen(nodename);
    const char* function[] = {"SEND_NAME", "SEND_CHALLENGE"};
    int res;

    if (f_chall)
	siz += 4;
    buf = (siz > DEFBUF_SIZ) ? malloc(siz) : dbuf;
    if (!buf) {
	erl_errno = ENOMEM;
	return -1;
    }
    s = (unsigned char *)buf;
    put16be(s,siz - 2);
    put8(s, 'n');
    put16be(s, version);
    put32be(s, (DFLAG_EXTENDED_REFERENCES
		| DFLAG_DIST_MONITOR
		| DFLAG_EXTENDED_PIDS_PORTS
		| DFLAG_FUN_TAGS
		| DFLAG_NEW_FUN_TAGS
                | DFLAG_NEW_FLOATS
		| DFLAG_SMALL_ATOM_TAGS
		| DFLAG_UTF8_ATOMS
		| DFLAG_MAP_TAG
		| DFLAG_BIG_CREATION));
    if (f_chall)
	put32be(s, challenge);
    memcpy(s, nodename, strlen(nodename));
    
    if ((res = ei_write_fill_t(fd, buf, siz, ms)) != siz) {
	EI_TRACE_ERR1("send_name_or_challenge",
		      "-> %s socket write failed", function[f_chall]);
	if (buf != dbuf)
	    free(buf);
	erl_errno = (res == -2) ? ETIMEDOUT : EIO;
	return -1;
    }
    
    if (buf != dbuf)
	free(buf);
    return 0;
}
示例#7
0
/* 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;

    if (len > sizeof(buf)-3) {
	erl_errno = ERANGE;
	return -1;
    }

    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;
}
示例#8
0
文件: send.c 项目: Dasudian/otp
int ei_send_encoded_tmo(int fd, const erlang_pid *to, 
			char *msg, int msglen, unsigned ms) 
{
    char *s, header[1200]; /* see size calculation below */
    erlang_trace *token = NULL;
    int index = 5; /* reserve 5 bytes for control message */
    int res;
#ifdef HAVE_WRITEV
    struct iovec v[2];
#endif

    /* are we tracing? */
    /* check that he can receive trace tokens first */
    if (ei_distversion(fd) > 0) token = ei_trace(0,NULL);
    
    /* header = SEND, cookie, to                      max sizes: */
    ei_encode_version(header,&index);		      /*   1 */
    if (token) {
	ei_encode_tuple_header(header,&index,4);      /*   2 */
	ei_encode_long(header,&index,ERL_SEND_TT);    /*   2 */
    } else {
	ei_encode_tuple_header(header,&index,3);
	ei_encode_long(header,&index,ERL_SEND); 
    }
    ei_encode_atom(header,&index,ei_getfdcookie(fd)); /* 258 */
    ei_encode_pid(header,&index,to);		      /* 268 */
    
    if (token) ei_encode_trace(header,&index,token);  /* 534 */
    
    /* control message (precedes header actually) */
    /* length = 1 ('p') + header len + message len */
    s = header;
    put32be(s, index + msglen - 4);		      /*   4 */
    put8(s, ERL_PASS_THROUGH);			      /*   1 */
				/*** sum: 1070 */

    if (ei_tracelevel >= 4)
	ei_show_sendmsg(stderr,header,msg);

#ifdef HAVE_WRITEV
    
    v[0].iov_base = (char *)header;
    v[0].iov_len = index;
    v[1].iov_base = (char *)msg;
    v[1].iov_len = msglen;
    
    if ((res = ei_writev_fill_t(fd,v,2,ms)) != index+msglen) {
	erl_errno = (res == -2) ? ETIMEDOUT : EIO;
	return -1;
    }
  
#else  /* !HAVE_WRITEV */
  
    if ((res = ei_write_fill_t(fd,header,index,ms)) != index) { 
	erl_errno = (res == -2) ? ETIMEDOUT : EIO;
	return -1;
    }
    if ((res = ei_write_fill_t(fd,msg,msglen,ms)) != msglen) { 
	erl_errno = (res == -2) ? ETIMEDOUT : EIO;
	return -1;
    }

#endif  /* !HAVE_WRITEV */

    return 0;
}
示例#9
0
/* 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;
  
  if (len > sizeof(buf)-2)
  {
    erl_errno = ERANGE;
    return -1;
  }

  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;
}
示例#10
0
文件: eirecv.c 项目: Bwooce/otp
/* length (4), PASS_THOUGH (1), header, message */
int 
ei_recv_internal (int fd, 
		  char **mbufp, int *bufsz, 
		  erlang_msg *msg, int *msglenp, 
		  int staticbufp, unsigned ms)
{
  char header[EIRECVBUF];
  char *s=header;
  char *mbuf=*mbufp;
  int len = 0;
  int msglen = 0;
  int bytesread = 0;
  int remain;
  int arity;
  int version;
  int index = 0;
  int i = 0;
  int res;
  int show_this_msg = 0;

  /* get length field */
  if ((res = ei_read_fill_t(fd, header, 4, ms)) != 4) 
  {
      erl_errno = (res == -2) ? ETIMEDOUT : EIO;
      return -1;
  }
  len = get32be(s);

  /* got tick - respond and return */
  if (!len) {
    char tock[] = {0,0,0,0};
    ei_write_fill_t(fd, tock, sizeof(tock), ms); /* Failure no problem */
    *msglenp = 0;
    return 0;			/* maybe flag ERL_EAGAIN [sverkerw] */
  }
  
  /* turn off tracing on each receive. it will be turned back on if
   * we receive a trace token.
   */
  ei_trace(-1,NULL);
  
  /* read enough to get at least entire header */
  bytesread = (len > EIRECVBUF ? EIRECVBUF : len); 
  if ((i = ei_read_fill_t(fd,header,bytesread,ms)) != bytesread) {
      erl_errno = (i == -2) ? ETIMEDOUT : EIO;
      return -1;
  }

  /* now decode header */
  /* pass-through, version, control tuple header, control message type */
  s = header;
  index = 1;
  if ((get8(s) != ERL_PASS_THROUGH)
      || ei_decode_version(header,&index,&version)
      || (version != ERL_VERSION_MAGIC) 
      || ei_decode_tuple_header(header,&index,&arity) 
      || ei_decode_long(header,&index,&msg->msgtype))
  {
      erl_errno = EIO;	/* Maybe another code for decoding errors */
      return -1;
  }
  
  switch (msg->msgtype) {
  case ERL_SEND:          /* { SEND, Cookie, ToPid } */
    if (ei_tracelevel >= 4) show_this_msg = 1;
    if (ei_decode_atom(header,&index,msg->cookie) 
	|| ei_decode_pid(header,&index,&msg->to))
    {
	erl_errno = EIO;
	return -1;
    }

    break;

  case ERL_REG_SEND:     /* { REG_SEND, From, Cookie, ToName } */
    if (ei_tracelevel >= 4) show_this_msg = 1;
    if (ei_decode_pid(header,&index,&msg->from) 
	|| ei_decode_atom(header,&index,msg->cookie) 
	|| ei_decode_atom(header,&index,msg->toname))
    {
	erl_errno = EIO;
	return -1;
    }

    /* actual message is remaining part of headerbuf, plus any unread bytes */
    break;

  case ERL_LINK:         /* { LINK, From, To } */
  case ERL_UNLINK:       /* { UNLINK, From, To } */
  case ERL_GROUP_LEADER: /* { GROUP_LEADER, From, To } */
    if (ei_tracelevel >= 4) show_this_msg = 1;
    if (ei_decode_pid(header,&index,&msg->from) 
	|| ei_decode_pid(header,&index,&msg->to))
    {
	erl_errno = EIO;
	return -1;
    }

    break;
    
  case ERL_EXIT:         /* { EXIT, From, To, Reason } */
  case ERL_EXIT2:        /* { EXIT2, From, To, Reason } */
    if (ei_tracelevel >= 4) show_this_msg = 1;
    if (ei_decode_pid(header,&index,&msg->from) 
	|| ei_decode_pid(header,&index,&msg->to))
    {
	erl_errno = EIO;
	return -1;
    }

    break;
    
  case ERL_SEND_TT:      /* { SEND_TT, Cookie, ToPid, TraceToken } */
    if (ei_tracelevel >= 4) show_this_msg = 1;
    if (ei_decode_atom(header,&index,msg->cookie) 
	|| ei_decode_pid(header,&index,&msg->to)
	|| ei_decode_trace(header,&index,&msg->token))
    {
	erl_errno = EIO;
	return -1;
    }

    ei_trace(1,&msg->token); /* turn on tracing */
    break;

  case ERL_REG_SEND_TT: /* { REG_SEND_TT, From, Cookie, ToName, TraceToken } */
    if (ei_tracelevel >= 4) show_this_msg = 1;
    if (ei_decode_pid(header,&index,&msg->from) 
	|| ei_decode_atom(header,&index,msg->cookie) 
	|| ei_decode_atom(header,&index,msg->toname)
	|| ei_decode_trace(header,&index,&msg->token))
    {
	erl_errno = EIO;
	return -1;
    }

    ei_trace(1,&msg->token); /* turn on tracing */
    break;

  case ERL_EXIT_TT:     /* { EXIT_TT, From, To, TraceToken, Reason } */
  case ERL_EXIT2_TT:    /* { EXIT2_TT, From, To, TraceToken, Reason } */
    if (ei_tracelevel >= 4) show_this_msg = 1;
    if (ei_decode_pid(header,&index,&msg->from) 
	|| ei_decode_pid(header,&index,&msg->to)
	|| ei_decode_trace(header,&index,&msg->token))
    {
	erl_errno = EIO;
	return -1;
    }

    ei_trace(1,&msg->token); /* turn on tracing */
    break;

  case ERL_NODE_LINK:   /* { NODE_LINK } */
    if (ei_tracelevel >= 4) show_this_msg = 1;
    break;

  default:
    /* unknown type, just put any remaining bytes into buffer */
    break;
  }

  /* actual message is remaining part of headerbuf, plus any unread bytes */
  msglen = len - index;     /* message size (payload) */
  remain = len - bytesread; /* bytes left to read */

  /* if callers buffer is too small, we flush in the rest of the
   * message and discard it, unless we know that we can reallocate
   * the buffer in which case we do that and read the message.
   */
  if (msglen > *bufsz) {
    if (staticbufp) {
      int sz = EIRECVBUF;
      /* flush in rest of packet */
      while (remain > 0) {
	if (remain < sz) sz = remain;
	if ((i=ei_read_fill_t(fd,header,sz,ms)) <= 0) break;
	remain -= i;
      }
      erl_errno = EMSGSIZE;
      return -1;
    }
    else {
	/* Dynamic buffer --- grow it. */
#ifdef DEBUG
      fprintf(stderr, "Growing buffer from %d bytes to %d bytes\n",
	      *bufsz, msglen);
#endif
      if ((mbuf = realloc(*mbufp, msglen)) == NULL)
      {
	  erl_errno = ENOMEM;
	  return -1;
      }

      *mbufp = mbuf;
      *bufsz = msglen;
    }  
  }
  
  /* move remaining bytes to callers buffer */
  memmove(mbuf,header+index,bytesread-index);

  /* let the caller know how big the message is in his buffer */
  *msglenp = msglen;

  /* read the rest of the message into callers buffer */
  if (remain > 0) {
    if ((i = ei_read_fill_t(fd,mbuf+bytesread-index,remain,ms)) != remain) {
      *msglenp = bytesread-index+1; /* actual bytes in users buffer */
      erl_errno = (i == -2) ? ETIMEDOUT : EIO;
      return -1;
    }
  }

  if (show_this_msg)
      ei_show_recmsg(stderr,msg,mbuf);

  /* the caller only sees "untraced" message types */
  /* the trace token is buried in the message struct */
  if (msg->msgtype > 10) msg->msgtype -= 10;
  
  return msg->msgtype;
}
示例#11
0
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

  if (len > sizeof(buf) - 3)
  {
      erl_errno = ERANGE;
      return -1;
  }
  
  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;
}
示例#12
0
int ei_write_fill(int fd, char *buf, int len) 
{
    return ei_write_fill_t(fd, buf, len, 0);
}