Пример #1
0
static uint64_t get64be(struct buffer *input)
{
	uint64_t ret;
	ret = get32be(input);
	ret <<= 32;
	ret |= get32be(input);
	return ret;
}
Пример #2
0
int ei_decode_ref(const char *buf, int *index, erlang_ref *p)
{
  const char *s = buf + *index;
  const char *s0 = s;
  int count, i;
  
  switch (get8(s)) {
    case ERL_REFERENCE_EXT:

      /* nodename */
      if (get_atom(&s, p->node, &p->node_org_enc) < 0) return -1;
  
      /* now the numbers: num (4), creation (1) */
      if (p) {
	  p->n[0] = get32be(s);
	  p->len = 1;
	  p->creation = get8(s) & 0x03;
      }
      else s += 5;
  
      *index += s-s0;
  
      return 0;
      break;
      
    case ERL_NEW_REFERENCE_EXT:
      /* first the integer count */
      count = get16be(s);
      if (p) p->len = count;

      /* then the nodename */
      if (get_atom(&s, p->node, &p->node_org_enc) < 0) return -1;

      /* creation */
      if (p) {
	  p->creation = get8(s) & 0x03;
      }
      else s += 1;

      /* finally the id integers */
      if (p) {
	for (i = 0; (i<count) && (i<3); i++) {
	  p->n[i] = get32be(s);
	}
      }
      else s += 4 * count;
  
      *index += s-s0;
  
      return 0;
      break;
      
    default:
      return -1;
  }
}
Пример #3
0
int ei_decode_ulong(const char *buf, int *index, unsigned long *p)
{
  const char *s = buf + *index;
  const char *s0 = s;
  unsigned long n;
  long sn;
  int arity;

  switch (get8(s)) {
  case ERL_SMALL_INTEGER_EXT:
    n = get8(s);
    break;
    
  case ERL_INTEGER_EXT:
    sn = get32be(s);
    if (sn < 0) return -1;
    n = (unsigned long)sn;
    break;
    
  case ERL_SMALL_BIG_EXT:
    arity = get8(s);
    goto decode_big;

  case ERL_LARGE_BIG_EXT:
    arity = get32be(s);

  decode_big:
    {
      int sign = get8(s);
      int i;
      n = 0;

      if (sign) return -1;

      /* Little Endian, up to four bytes always fit into unsigned long */
      for (i = 0; i < arity; i++) {
	if (i < 4) {
	  n |= get8(s) << (i * 8);
	} else if (get8(s) != 0) {
	  return -1; /* All but first byte have to be 0 */
	}
      }
    }
    break;
    
  default:
    return -1;
  }

  if (p) *p = (unsigned long)n;
  *index += s-s0;
  
  return 0; 
}
Пример #4
0
int ei_get_type_internal(const char *buf, const int *index,
			 int *type, int *len)
{
  const char *s = buf + *index;

  *type = get8(s);
  
  switch (*type) {
  case ERL_SMALL_TUPLE_EXT:
    *len = get8(s);
    break;
    
  case ERL_ATOM_EXT:
  case ERL_STRING_EXT:
    *len = get16be(s);
    break;

  case ERL_FLOAT_EXT:
  case NEW_FLOAT_EXT:
    *type = ERL_FLOAT_EXT;
    break;

  case ERL_LARGE_TUPLE_EXT:
  case ERL_LIST_EXT:
  case ERL_BINARY_EXT:
    *len = get32be(s);
    break;
    
  case ERL_SMALL_BIG_EXT:
    *len = get8(s); /* #digit_bytes */
    break;

  case ERL_LARGE_BIG_EXT:
    *len = get32be(s); /* #digit_bytes */
    break;

  default:
    *len = 0;
    break;
  }

  /* leave index unchanged */
  return 0;
}
Пример #5
0
int ei_decode_intlist(const char *buf, int *index, long *a, int *count)
{
  const unsigned char *s = (const unsigned char *)(buf + *index);
  const unsigned char *s0 = s;
  int idx;
  int len;
  int i;

  switch (get8(s)) {
  case ERL_STRING_EXT:
    len = get16be(s);

    /* transfer and cast chars one at a time into array */
    if (a) {
      for (i=0; i<len; i++) {
	a[i] = (long)(s[i]);
      }
    }
    if (count) *count = len;
    s += len;
    break;

  case ERL_LIST_EXT:
    len = get32be(s);
    idx = 0;
    
    if (a) {
      for (i=0; i<len; i++) {
	if (ei_decode_long((char*)s,&idx,a+i) < 0) {
	  if (count) *count = i;
	  return -1;
	}
      }
    }
    else {
      for (i=0; i<len; i++) {
	if (ei_decode_long((char*)s,&idx,NULL) < 0) {
	  if (count) *count = i;
	  return -1;
	}
      }
    }

    if (count) *count = len;
    s += idx;
    break;

  default:
    return -1;
  }


  *index += s-s0; 

  return 0; 
}
Пример #6
0
static int recv_challenge_reply (int fd, 
				 unsigned our_challenge,
				 char cookie[], 
				 unsigned *her_challenge,
				 unsigned ms)
{
    char dbuf[DEFBUF_SIZ];
    char *buf = dbuf;
    int is_static = 1;
    int buflen = DEFBUF_SIZ;
    int rlen;
    char *s;
    char tag;
    char her_digest[16], expected_digest[16];
    
    erl_errno = EIO;		/* Default */

    if ((rlen = read_2byte_package(fd, &buf, &buflen, &is_static, ms)) != 21) {
	EI_TRACE_ERR1("recv_challenge_reply",
		      "<- RECV_CHALLENGE_REPLY socket read failed (%d)",rlen);
	goto error;
    }
    
    s = buf;
    if ((tag = get8(s)) != 'r') {
	EI_TRACE_ERR2("recv_challenge_reply",
		      "<- RECV_CHALLENGE_REPLY incorrect tag, "
		      "expected 'r' got '%c' (%u)",tag,tag);
	goto error;
    }
    *her_challenge = get32be(s);
    memcpy(her_digest, s, 16);
    gen_digest(our_challenge, cookie, (unsigned char*)expected_digest);
    if (memcmp(her_digest, expected_digest, 16)) {
	EI_TRACE_ERR0("recv_challenge_reply",
		      "<- RECV_CHALLENGE_REPLY authorization failure");
	goto error;
    }
    if (!is_static)
	free(buf);

   
    if (ei_tracelevel >= 3) {
	char buffer[33];	
        EI_TRACE_CONN2("recv_challenge_reply",
		   "<- RECV_CHALLENGE_REPLY (ok) challenge = %u, digest = %s",
		   *her_challenge,hex(her_digest,buffer));
    }
    erl_errno = 0;
    return 0;
    
error:
    if (!is_static)
	free(buf);
    return -1;
}
Пример #7
0
void play_audio(sdl_data *sd, int len, char *buff) 
{
   char *bp, *start;
   int sendlen;
   void * sbuff;
   bp = buff;
   
   SDL_LockAudio();   
   
   POPGLPTR(sbuff, bp);
   wave.sound    = sbuff;
   wave.soundlen = get32be(bp);
   wave.repeat   = get32be(bp);
   wave.soundpos = 0;
   
   SDL_UnlockAudio();
   bp = start = sdl_getbuff(sd, 0);
   sendlen = (int) (bp - start);
   sdl_send(sd, sendlen);
}
Пример #8
0
void es_convertAudio(sdl_data *sd, int len, char *buff)
{
   char *bp, *start;
   void *mptr;
   Uint16 oformat, nformat;
   Uint8  ochannels, nchannels;
   int    ofreq, nfreq, osize, nsize;
   SDL_AudioCVT  wav_cvt;
   int sendlen;

   bp = buff;
   oformat = get16be(bp);
   ochannels = get8(bp);
   ofreq = get32be(bp);
   nformat = get16be(bp);
   nchannels = get8(bp);
   nfreq = get32be(bp);
   POPGLPTR(mptr, bp);
   osize = get32be(bp);

   bp = start = sdl_getbuff(sd, 12);
   
   /* Build AudioCVT */
   if(SDL_BuildAudioCVT(&wav_cvt,oformat, ochannels, ofreq,
			nformat, nchannels, nfreq) >= 0) {      
      /* Setup for conversion */
      nsize = osize*wav_cvt.len_mult;      
      wav_cvt.buf=(Uint8 *)malloc(nsize);
      if(wav_cvt.buf != NULL) {
	 wav_cvt.len=osize;
	 memcpy(wav_cvt.buf, mptr, osize);
	 if (SDL_ConvertAudio(&wav_cvt) >= 0) {
	   PUSHGLPTR(wav_cvt.buf, bp);
	   put32be(bp, nsize);	 	
	 }
      }
   }   
   sendlen = (int) (bp - start);
   sdl_send(sd, sendlen);
}
Пример #9
0
void es_joystick_eventState(sdl_data *sd, int len,char *buff)
{
   int sendlen;
   char *bp, *start;
   int state;
   
   bp = buff;
   state = get32be(bp);
   bp = start = sdl_get_temp_buff(sd, 4);
   state = SDL_JoystickEventState(state);
   put32be(bp, state);
   sendlen = bp - start;
   sdl_send(sd, sendlen);
}
Пример #10
0
int ei_decode_binary(const char *buf, int *index, void *p, long *lenp)
{
  const char *s = buf + *index;
  const char *s0 = s;
  long len;

  if (get8(s) != ERL_BINARY_EXT) return -1;

  len = get32be(s);
  if (p) memmove(p,s,len);
  s += len;

  if (lenp) *lenp = len;
  *index += s-s0; 

  return 0; 
}
Пример #11
0
void es_openAudio(sdl_data *sd, int len, char *buff)
{
   int sendlen;
   char *bp, *start;
   int ff;
   SDL_AudioSpec desired, obtained, *obptr;
   bp = buff;
   ff = get8(bp);
   desired.freq     = get32be(bp);
   desired.format   = get16be(bp);
   desired.channels = get8(bp);
   desired.samples  = get16be(bp);
   desired.padding  = get16be(bp);
   desired.callback = myaudiomixer;

   /* Init the global data structures */
   wave.sound = NULL;
   wave.soundpos = 0;
   wave.soundlen = 0;

   if(ff == 1)  /* Force the requested format */
      obptr = NULL;
   else 
      obptr = &obtained;
   
   bp = start = sdl_getbuff(sd, 16);
   if( SDL_OpenAudio(&desired, obptr) < 0 ) {
      fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());		
   } else {
      if(ff == 1) 
	  obptr = &desired;
       put32be(bp, obptr->freq);
       put16be(bp, obptr->format);
       put8(bp, obptr->channels);
       put8(bp, obptr->silence);
       put16be(bp, obptr->samples);
       put16be(bp, obptr->padding);
       put32be(bp, obptr->size);
       wave.silence = obptr->silence;
   } 
  
   sendlen = (int) (bp - start);
   sdl_send(sd, sendlen);
}
Пример #12
0
int ei_decode_port(const char *buf, int *index, erlang_port *p)
{
  const char *s = buf + *index;
  const char *s0 = s;
  
  if (get8(s) != ERL_PORT_EXT) return -1;

  /* first the nodename */
  if (get_atom(&s, p->node, &p->node_org_enc) < 0) return -1;
  
  /* now the numbers: num (4), creation (1) */
  if (p) {
    p->id = get32be(s) & 0x0fffffff /* 28 bits */;
    p->creation = get8(s) & 0x03;
  }
  else s += 5;
  
  *index += s-s0;
  
  return 0;
}
Пример #13
0
static int ei_decode_skip_bignum(const char *buf, int *index, void *p)
{
    const char *s = buf + *index;
    const char *s0 = s;
    long n;

    switch (get8(s)) {
    case ERL_LARGE_BIG_EXT:
        n = get32be(s);
        s += n+1;
        break;

    default:
        erl_errno = EIO;
        return -1;
    }

    *index += s-s0;

    return 0;
}
Пример #14
0
int ei_decode_fun(const char *buf, int *index, erlang_fun *p)
{
    const char *s = buf + *index;
    const char *s0 = s;
    int i, ix, ix0, n;
    erlang_pid* p_pid;
    char* p_module;
    erlang_char_encoding* p_module_org_enc;
    long* p_index;
    long* p_uniq;
    long* p_old_index;

    if (p != NULL) {
	p_pid = &p->pid;
	p_module = &p->module[0];
	p_module_org_enc = &p->module_org_enc;
	p_index = &p->index;
	p_uniq = &p->uniq;
	p_old_index = &p->old_index;
    }
    else {
	p_pid = NULL; p_module = NULL; p_module_org_enc = NULL;
	p_index = NULL; p_uniq = NULL; p_old_index = NULL;
    }

    switch (get8(s)) {
    case ERL_FUN_EXT:
	/* mark as old (R7 and older) external fun */
	if (p != NULL) p->arity = -1;
	/* first number of free vars (environment) */
	n = get32be(s);
	/* then the pid */
	ix = 0;
	if (ei_decode_pid(s, &ix, p_pid) < 0)
	    return -1;
	/* then the module (atom) */
	if (ei_decode_atom_as(s, &ix, p_module, MAXATOMLEN_UTF8, ERLANG_UTF8,
			      p_module_org_enc, NULL) < 0)
	    return -1;
	/* then the index */
	if (ei_decode_long(s, &ix, p_index) < 0)
	    return -1;
	/* then the uniq */
	if (ei_decode_long(s, &ix, p_uniq) < 0)
	    return -1;
	/* finally the free vars */
	ix0 = ix;
	for (i = 0; i < n; ++i) {
	    if (ei_skip_term(s, &ix) < 0)
		return -1;
	}
	if (p != NULL) {
	    p->n_free_vars = n;
	    p->free_var_len = ix - ix0;
	    p->free_vars = ei_malloc(ix - ix0);
	    if (!(p->free_vars)) return -1;
	    memcpy(p->free_vars, s + ix0, ix - ix0);
	}
	s += ix;
	*index += s-s0;
        return 0;
	break;
    case ERL_NEW_FUN_EXT:
	/* first total size */
	n = get32be(s);
	/* then the arity */
	i = get8(s);
	if (p != NULL) p->arity = i;
	/* then md5 */
	if (p != NULL) memcpy(p->md5, s, 16);
	s += 16;
	/* then index */
	i = get32be(s);
	if (p != NULL) p->index = i;
	/* then the number of free vars (environment) */
	i = get32be(s);
	if (p != NULL) p->n_free_vars = i;
	/* then the module (atom) */
	ix = 0;
	if (ei_decode_atom_as(s, &ix, p_module, MAXATOMLEN_UTF8, ERLANG_UTF8,
			      p_module_org_enc, NULL) < 0)
	    return -1;
	/* then the old_index */
	if (ei_decode_long(s, &ix, p_old_index) < 0)
	    return -1;
	/* then the old_uniq */
	if (ei_decode_long(s, &ix, p_uniq) < 0)
	    return -1;
	/* the the pid */
	if (ei_decode_pid(s, &ix, p_pid) < 0)
	    return -1;
	/* finally the free vars */
	s += ix;
	n = n - (s - s0) + 1;
	if (n < 0) return -1;
	if (p != NULL) {
	    p->free_var_len = n;
	    if (n > 0) {
		p->free_vars = malloc(n);
		if (!(p->free_vars)) return -1;
		memcpy(p->free_vars, s, n);
	    }
	}
	s += n;
	*index += s-s0;
        return 0;
	break;
    default:
	return -1;
    }
}
Пример #15
0
static int recv_name(int fd, 
		     unsigned *version,
		     unsigned *flags, ErlConnect *namebuf, unsigned ms)
{
    char dbuf[DEFBUF_SIZ];
    char *buf = dbuf;
    int is_static = 1;
    int buflen = DEFBUF_SIZ;
    int rlen;
    char *s;
    struct sockaddr_in sin;
    socklen_t sin_len = sizeof(sin);
    char tag;
    
    erl_errno = EIO;		/* Default */

    if ((rlen = read_2byte_package(fd, &buf, &buflen, &is_static, ms)) <= 0) {
	EI_TRACE_ERR1("recv_name","<- RECV_NAME socket read failed (%d)",rlen);
	goto error;
    }
    if ((rlen - 7) > MAXNODELEN) {
	EI_TRACE_ERR1("recv_name","<- RECV_NAME nodename too long (%d)",rlen-7);
	goto error;
    }
    s = buf;
    tag = get8(s);
    if (tag != 'n') {
	EI_TRACE_ERR2("recv_name","<- RECV_NAME incorrect tag, "
		      "expected 'n' got '%c' (%u)",tag,tag);
	goto error;
    }
    *version = get16be(s);
    *flags = get32be(s);

    if (!(*flags & DFLAG_EXTENDED_REFERENCES)) {
	EI_TRACE_ERR0("recv_name","<- RECV_NAME peer cannot handle"
		      "extended references");
	goto error;
    }

    if (!(*flags & DFLAG_EXTENDED_PIDS_PORTS)
	&& !ei_internal_use_r9_pids_ports()) {
	EI_TRACE_ERR0("recv_name","<- RECV_NAME peer cannot "
		      "handle extended pids and ports");
	erl_errno = EIO;
	goto error;
    }
	  
    if (getpeername(fd, (struct sockaddr *) &sin, &sin_len) < 0) {
	EI_TRACE_ERR0("recv_name","<- RECV_NAME can't get peername");
	erl_errno = errno;
	goto error;
    }
    memcpy(namebuf->ipadr, &(sin.sin_addr.s_addr), 
	sizeof(sin.sin_addr.s_addr));
    memcpy(namebuf->nodename, s, rlen - 7);
    namebuf->nodename[rlen - 7] = '\0';
    if (!is_static)
	free(buf);
    EI_TRACE_CONN3("recv_name",
		   "<- RECV_NAME (ok) node = %s, version = %u, flags = %u",
		   namebuf->nodename,*version,*flags);
    erl_errno = 0;
    return 0;
    
error:
    if (!is_static)
	free(buf);
    return -1;
}
Пример #16
0
int ei_decode_ei_term(const char* buf, int* index, ei_term* term)
{
    const char* s = buf + *index, * s0 = s;
    int n, sign;
    char c;

    if (term == NULL) return -1;
    c = term->ei_type = get8(s);
    switch (c) {
    case ERL_SMALL_INTEGER_EXT:
	term->value.i_val = get8(s);
	break;
    case ERL_INTEGER_EXT:
	term->value.i_val = get32be(s);
	break;
    case ERL_FLOAT_EXT:
    case NEW_FLOAT_EXT:
        return (ei_decode_double(buf, index, &term->value.d_val) < 0
                ? -1 : 1);
    case ERL_ATOM_EXT:
    case ERL_ATOM_UTF8_EXT:
    case ERL_SMALL_ATOM_EXT:
    case ERL_SMALL_ATOM_UTF8_EXT:
	return (ei_decode_atom(buf, index, term->value.atom_name) < 0
                ? -1 : 1);
    case ERL_REFERENCE_EXT:
    case ERL_NEW_REFERENCE_EXT:
    case ERL_NEWER_REFERENCE_EXT:
        return (ei_decode_ref(buf, index, &term->value.ref) < 0
                ? -1 : 1);
    case ERL_PORT_EXT:
    case ERL_NEW_PORT_EXT:
        return (ei_decode_port(buf, index, &term->value.port) < 0
                ? -1 : 1);
    case ERL_PID_EXT:
    case ERL_NEW_PID_EXT:
        return (ei_decode_pid(buf, index, &term->value.pid) < 0
                ? -1 : 1);
    case ERL_SMALL_TUPLE_EXT:
	term->arity = get8(s);
	break;
    case ERL_LARGE_TUPLE_EXT:
	term->arity = get32be(s);
	break;
    case ERL_NIL_EXT:
	term->arity = 0;
	break;
    case ERL_STRING_EXT:
	term->size = get16be(s);
	return 0;
    case ERL_LIST_EXT:
    case ERL_MAP_EXT:
	term->arity = get32be(s);
	break;
    case ERL_BINARY_EXT:
	term->size = get32be(s);
	return 0;
    case ERL_SMALL_BIG_EXT:
	if ((term->arity = get8(s)) != 4) return -1;
	sign = get8(s);
	/* Little Endian, and n always positive, except for LONG_MIN */
	n = get32le(s);
	if (sign) {
	    /* check for overflow */
	    if ((n - 1) < 0) return -1;
	    n = -n;
	} else {
	    /* check for overflow */
	    if (n < 0) return -1;
	}
	break;
    case ERL_LARGE_BIG_EXT:
	return 0;
    case ERL_PASS_THROUGH:
	return 0;
    case ERL_NEW_CACHE:
	return -1;
    case ERL_CACHED_ATOM:
	return -1;
    default:
	return -1;
    }
    *index += s-s0;
    return 1;
}
Пример #17
0
int ei_decode_ei_term(const char* buf, int* index, ei_term* term)
{
    const char* s = buf + *index, * s0 = s;
    int i, n, sign;
    char c;

    if (term == NULL) return -1;
    c = term->ei_type = get8(s);
    switch (c) {
    case ERL_SMALL_INTEGER_EXT:
	term->value.i_val = get8(s);
	break;
    case ERL_INTEGER_EXT:
	term->value.i_val = get32be(s);
	break;
    case ERL_FLOAT_EXT:
    case NEW_FLOAT_EXT:
        return ei_decode_double(buf, index, &term->value.d_val);
    case ERL_ATOM_EXT:
    case ERL_ATOM_UTF8_EXT:
    case ERL_SMALL_ATOM_EXT:
    case ERL_SMALL_ATOM_UTF8_EXT:
	return ei_decode_atom(buf, index, term->value.atom_name);
    case ERL_REFERENCE_EXT:
	/* first the nodename */
	if (get_atom(&s, term->value.ref.node, &term->value.ref.node_org_enc) < 0) return -1;
        /* now the numbers: num (4), creation (1) */
	term->value.ref.n[0] = get32be(s);
	term->value.ref.len = 1;
	term->value.ref.creation = get8(s) & 0x03;
	break;
    case ERL_NEW_REFERENCE_EXT:
	/* first the integer count */
	term->value.ref.len = get16be(s);
	/* then the nodename */
	if (get_atom(&s, term->value.ref.node, &term->value.ref.node_org_enc) < 0) return -1;
	/* creation */
	term->value.ref.creation = get8(s) & 0x03;
	/* finally the id integers */
	for (i = 0; (i<term->value.ref.len) && (i<3); i++) {
	    term->value.ref.n[i] = get32be(s);
	}
	if (term->value.ref.len > 3) {
	    s += 4 * (term->value.ref.len - 3);
	}
	break;
    case ERL_PORT_EXT:
	if (get_atom(&s, term->value.port.node, &term->value.port.node_org_enc) < 0) return -1;
	term->value.port.id = get32be(s) & 0x0fffffff; /* 28 bits */;
	term->value.port.creation = get8(s) & 0x03;
	break;
    case ERL_PID_EXT:
	if (get_atom(&s, term->value.pid.node, &term->value.port.node_org_enc) < 0) return -1;
	/* now the numbers: num (4), serial (4), creation (1) */
	term->value.pid.num = get32be(s) & 0x7fff; /* 15 bits */
	term->value.pid.serial = get32be(s) & 0x1fff; /* 13 bits */
	term->value.pid.creation = get8(s) & 0x03; /* 2 bits */
	break;
    case ERL_SMALL_TUPLE_EXT:
	term->arity = get8(s);
	break;
    case ERL_LARGE_TUPLE_EXT:
	term->arity = get32be(s);
	break;
    case ERL_NIL_EXT:
	term->arity = 0;
	break;
    case ERL_STRING_EXT:
	term->size = get16be(s);
	return 0;
    case ERL_LIST_EXT:
	term->arity = get32be(s);
	break;
    case ERL_BINARY_EXT:
	term->size = get32be(s);
	return 0;
    case ERL_SMALL_BIG_EXT:
	if ((term->arity = get8(s)) != 4) return -1;
	sign = get8(s);
	/* Little Endian, and n always positive, except for LONG_MIN */
	n = get32le(s);
	if (sign) {
	    /* check for overflow */
	    if ((n - 1) < 0) return -1;
	    n = -n;
	} else {
	    /* check for overflow */
	    if (n < 0) return -1;
	}
	break;
    case ERL_LARGE_BIG_EXT:
	return 0;
    case ERL_PASS_THROUGH:
	return 0;
    case ERL_NEW_CACHE:
	return -1;
    case ERL_CACHED_ATOM:
	return -1;
    default:
	return -1;
    }
    *index += s-s0;
    return 1;
}
Пример #18
0
/* 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;
}
Пример #19
0
int ei_decode_longlong(const char *buf, int *index, EI_LONGLONG *p)
{
    const char *s = buf + *index;
    const char *s0 = s;
    EI_LONGLONG n;
    int arity;

    switch (get8(s)) {
    case ERL_SMALL_INTEGER_EXT:
	n = get8(s);
	break;
    
    case ERL_INTEGER_EXT:
	n = get32be(s);
	break;
    
    case ERL_SMALL_BIG_EXT:
	arity = get8(s);
	goto decode_big;

    case ERL_LARGE_BIG_EXT:
	arity = get32be(s);

    decode_big:
	{
	    int sign = get8(s);
	    int i;
	    EI_ULONGLONG u = 0;

	    /* Little Endian, and n always positive, except for LONG_MIN */
	    for (i = 0; i < arity; i++) {
		if (i < 8) {
		    /* Use ULONGLONG not to get a negative integer if > 127 */
		    u |= ((EI_ULONGLONG)get8(s)) << (i * 8);
		} else if (get8(s) != 0) {
		    return -1; /* All but first byte have to be 0 */
		}
	    }

	    /* check for overflow */
	    if (sign) {
		if (u > MAX_TO_NEGATE) {
		    return -1;
		}
		n = -((EI_LONGLONG) u);
	    } else {
		if (u > MAX_TO_NOT_NEGATE) {
		    return -1;
		}
		n = (EI_LONGLONG) u;
	    }
	}
	break;
    
    default:
	return -1;
    }

    if (p) *p = n;
    *index += s-s0;
  
    return 0; 
}
Пример #20
0
static void show_term(const char *termbuf, int *index, FILE *stream)
{
    int type;
    char smallbuf[EISHOWBUF];
    int version;
    long num;
    double fnum;
    erlang_pid pid;
    erlang_port port;
    erlang_ref ref;
    int i, len;
    char *s;

    ei_get_type_internal(termbuf,index,&type,&len);

    switch (type) {
    case ERL_VERSION_MAGIC:
        /* just skip past this */
        ei_decode_version(termbuf,index,&version);
        show_term(termbuf,index,stream);
        break;

    case ERL_ATOM_EXT:
        ei_decode_atom(termbuf,index,smallbuf);
        fprintf(stream,"%s",smallbuf);
        break;

    case ERL_STRING_EXT:
        /* strings can be much longer than EISHOWBUF */
        if (len < EISHOWBUF) s = smallbuf;
        else if (!(s = malloc(len+1))) break; /* FIXME just break if can't? */

        ei_decode_string(termbuf,index,s);

        if (printable_list_p((uint8 *)s,len)) {
            /* just show it as it is */
            fprintf(stream,"\"%s\"",s);
        } else {
            /* show it as a list instead */
            fprintf(stream,"[");
            for (i=0; i<len; i++) {
                if (i > 0) fprintf(stream,", ");
                fprintf(stream,"%d",s[i]);
            }
            fprintf(stream,"]");
        }

        /* did we allocate anything? */
        if (s && (s != smallbuf)) free(s);

        break;

    /* FIXME add case using ei_decode_longlong */
    case ERL_SMALL_BIG_EXT:
    case ERL_SMALL_INTEGER_EXT:
    case ERL_INTEGER_EXT:
        if (ei_decode_long(termbuf,index,&num) == 0) {
            fprintf(stream,"%ld",num);
        } else {
            ei_decode_skip_bignum(termbuf,index,NULL);
            fprintf(stream,"#Bignum");
        }
        break;

    case ERL_FLOAT_EXT:
    case NEW_FLOAT_EXT:
        ei_decode_double(termbuf,index,&fnum);
        fprintf(stream,"%f",fnum);
        break;

    case ERL_PID_EXT:
        ei_decode_pid(termbuf,index,&pid);
        show_pid(stream,&pid);
        break;

    case ERL_SMALL_TUPLE_EXT:
    case ERL_LARGE_TUPLE_EXT:
        ei_decode_tuple_header(termbuf,index,&len);
        fprintf(stream,"{");
        for (i=0; i<len; i++) {
            if (i > 0) fprintf(stream,", ");
            show_term(termbuf,index,stream);
        }
        fprintf(stream,"}");
        break;

    case ERL_LIST_EXT:
        ei_decode_list_header(termbuf,index,&len);
        fprintf(stream,"[");
        for (i=0; i<len; i++) {
            if (i > 0) fprintf(stream,", ");
            show_term(termbuf,index,stream);
        }
        /* get the empty list at the end */
        ei_decode_list_header(termbuf,index,&len);
        fprintf(stream,"]");
        break;

    case ERL_NIL_EXT:
        ei_decode_list_header(termbuf,index,&len);
        fprintf(stream,"[]");
        break;

    case ERL_REFERENCE_EXT:
    case ERL_NEW_REFERENCE_EXT:
        ei_decode_ref(termbuf,index,&ref);
        fprintf(stream,"#Ref<%s",ref.node);
        for (i = 0; i < ref.len; i++) {
            fprintf(stream,".%u",ref.n[i]);
        }
        fprintf(stream,".%u>",ref.creation);
        break;

    case ERL_PORT_EXT:
        ei_decode_port(termbuf,index,&port);
        fprintf(stream,"#Port<%s.%u.%u>",port.node,port.id,port.creation);
        break;

    case ERL_BINARY_EXT:
        ei_decode_binary(termbuf,index,NULL,&num);
        fprintf(stream,"#Bin<%ld>",num);
        break;

    case ERL_LARGE_BIG_EXT:
        /* doesn't actually decode - just skip over it */
        /* FIXME if GMP, what to do here?? */
        ei_decode_skip_bignum(termbuf,index,NULL);
        fprintf(stream,"#Bignum");
        break;

    case ERL_FUN_EXT: {
        char atom[MAXATOMLEN];
        long idx;
        long uniq;
        const char* s = termbuf + *index, * s0 = s;
        int n_free;

        ++s;
        n_free = get32be(s);
        *index += s - s0;
        ei_decode_pid(termbuf, index, NULL); /* skip pid */
        ei_decode_atom(termbuf, index, atom); /* get module, index, uniq */
        ei_decode_long(termbuf, index, &idx);
        ei_decode_long(termbuf, index, &uniq);
        fprintf(stream,"#Fun<%s.%ld.%ld>", atom, idx, uniq);
        for (i = 0; i < n_free; ++i) {
            /* FIXME how to report error ?! */
            if (ei_skip_term(termbuf, index) != 0)
                fprintf(stderr,"<ERROR> show_msg: unknown type of term !");
        }
        break;
    }
    default:
        fprintf(stream,"#Unknown<%d.%d>",type,len);
        /* unfortunately we don't know how to skip over this type in
         * the buffer if we don't even know what it is, so we return.
         */
        return;
        break;
    }
}
Пример #21
0
int ei_get_type(const char *buf, const int *index, int *type, int *len)
{
    const char *s = buf + *index;
    int itype = get8(s);	/* Internal type */

    *len = 0;
  
    switch (*type) {

    case ERL_SMALL_INTEGER_EXT:
    case ERL_INTEGER_EXT:
    case ERL_SMALL_BIG_EXT:
    case ERL_LARGE_BIG_EXT:
	*type = EI_TYPE_INTEGER;
	break;

    case ERL_FLOAT_EXT:
	*type = EI_TYPE_FLOAT;
	break;

    case ERL_SMALL_TUPLE_EXT:
	*len  = get8(s);
	break;
    
    case ERL_ATOM_EXT:
    case ERL_STRING_EXT:
	*len  = get16be(s);
	break;
    
    case ERL_LARGE_TUPLE_EXT:
    case ERL_LIST_EXT:
    case ERL_BINARY_EXT:
	*len  = get32be(s);
	break;
    
    case ERL_SMALL_BIG_EXT:
	*len  = (get8(s)+1)/2; /* big arity */
	break;

    case ERL_LARGE_BIG_EXT:
	*len  = (get32be(s)+1)/2; /* big arity */
	break;

    case ERL_BINARY_EXT:
	*type = EI_TYPE_BINARY;
	break;

    case ERL_PID_EXT:
	*type = EI_TYPE_PID;
	break;

    case ERL_PORT_EXT:
	*type = EI_TYPE_PORT;
	break;

    case ERL_REFERENCE_EXT:
    case ERL_NEW_REFERENCE_EXT:
	*type = EI_TYPE_REF;
	break;

    default:
	break;
    }

    /* leave index unchanged */
    return 0;
}
Пример #22
0
int ei_decode_fun(const char *buf, int *index, erlang_fun *p)
{
    const char *s = buf + *index;
    const char *s0 = s;
    int i, ix, ix0, n;

    switch (get8(s)) {
    case ERL_FUN_EXT:
	/* mark as old (R7 and older) external fun */
	if (p != NULL) p->arity = -1;
	/* first number of free vars (environment) */
	n = get32be(s);
	/* then the pid */
	ix = 0;
	if (ei_decode_pid(s, &ix, (p == NULL ? (erlang_pid*)NULL : &p->pid)) < 0)
	    return -1;
	/* then the module (atom) */
	if (ei_decode_atom(s, &ix, (p == NULL ? (char*)NULL : p->module)) < 0)
	    return -1;
	/* then the index */
	if (ei_decode_long(s, &ix, (p == NULL ? (long*)NULL : &p->index)) < 0)
	    return -1;
	/* then the uniq */
	if (ei_decode_long(s, &ix, (p == NULL ? (long*)NULL : &p->uniq)) < 0)
	    return -1;
	/* finally the free vars */
	ix0 = ix;
	for (i = 0; i < n; ++i) {
	    if (ei_skip_term(s, &ix) < 0)
		return -1;
	}
	if (p != NULL) {
	    p->n_free_vars = n;
	    p->free_var_len = ix - ix0;
	    p->free_vars = ei_malloc(ix - ix0);	/* FIXME check result */
	    memcpy(p->free_vars, s + ix0, ix - ix0);
	}
	s += ix;
	*index += s-s0;
        return 0;
	break;
    case ERL_NEW_FUN_EXT:
	/* first total size */
	n = get32be(s);
	/* then the arity */
	i = get8(s);
	if (p != NULL) p->arity = i;
	/* then md5 */
	if (p != NULL) memcpy(p->md5, s, 16);
	s += 16;
	/* then index */
	i = get32be(s);
	if (p != NULL) p->index = i;
	/* then the number of free vars (environment) */
	i = get32be(s);
	if (p != NULL) p->n_free_vars = i;
	/* then the module (atom) */
	ix = 0;
	if (ei_decode_atom(s, &ix, (p == NULL ? (char*)NULL : p->module)) < 0)
	    return -1;
	/* then the old_index */
	if (ei_decode_long(s, &ix, (p == NULL ? (long*)NULL : &p->old_index)) < 0)
	    return -1;
	/* then the old_uniq */
	if (ei_decode_long(s, &ix, (p == NULL ? (long*)NULL : &p->uniq)) < 0)
	    return -1;
	/* the the pid */
	if (ei_decode_pid(s, &ix, (p == NULL ? (erlang_pid*)NULL : &p->pid)) < 0)
	    return -1;
	/* finally the free vars */
	s += ix;
	n = n - (s - s0) + 1;
	if (p != NULL) {
	    p->free_var_len = n;
	    if (n > 0) {
		p->free_vars = malloc(n); /* FIXME check result */
		memcpy(p->free_vars, s, n);
	    }
	}
	*index += s-s0;
        return 0;
	break;
    default:
	return -1;
    }
}