static uint64_t get64be(struct buffer *input) { uint64_t ret; ret = get32be(input); ret <<= 32; ret |= get32be(input); return ret; }
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; } }
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; }
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; }
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; }
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; }
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); }
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); }
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); }
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; }
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); }
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; }
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; }
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; } }
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; }
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; }
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; }
/* 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; }
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; }
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; } }
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; }
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; } }