static uint32_t get32be(struct buffer *input) { uint32_t ret; ret = get16be(input)<<16; ret |= get16be(input); return ret; }
void es_enableKeyRepeat(sdl_data *sd, int len,char *buff) { int sendlen; char *bp, *start; Uint16 delay, intv, res; bp = buff; delay = get16be(bp); intv = get16be(bp); bp = start = sdl_get_temp_buff(sd, 1); res = SDL_EnableKeyRepeat(delay, intv); put8(bp, res); sendlen = bp - start; sdl_send(sd, sendlen); }
/* c non-zero -> erlang "true" atom, otherwise "false" */ int ei_decode_boolean(const char *buf, int *index, int *p) { const char *s = buf + *index; const char *s0 = s; int len; int t; if (get8(s) != ERL_ATOM_EXT) return -1; len = get16be(s); switch (len) { case 4: /* typecast makes ansi happy */ if (strncmp((char*)s,"true",4)) return -1; t = 1; break; case 5: if (strncmp((char*)s,"false",5)) return -1; t = 0; break; default: return -1; } s += len; if (p) *p = t; *index += s-s0; return 0; }
void es_setModState(sdl_data *sd, int len,char *buff) { char *bp; Uint16 state; bp = buff; state = get16be(bp); SDL_SetModState(state); }
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_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_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; }
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_getKeyName(sdl_data *sd, int len,char *buff) { int sendlen; char *bp, *start, *name; Uint16 key; bp = buff; key = get16be(bp); bp = start = sdl_get_temp_buff(sd, 128); name = SDL_GetKeyName(key); while(*name != '\0') { put8(bp, *name); name++; } sendlen = bp - start; sdl_send(sd, sendlen); }
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; }
static int read_2byte_package(int fd, char **buf, int *buflen, int *is_static, unsigned ms) { unsigned char nbuf[2]; unsigned char *x = nbuf; unsigned len; int res; if((res = ei_read_fill_t(fd, (char *)nbuf, 2, ms)) != 2) { erl_errno = (res == -2) ? ETIMEDOUT : EIO; return -1; } len = get16be(x); if (len > *buflen) { if (*is_static) { char *tmp = malloc(len); if (!tmp) { erl_errno = ENOMEM; return -1; } *buf = tmp; *is_static = 0; *buflen = len; } else { char *tmp = realloc(*buf, len); if (!tmp) { erl_errno = ENOMEM; return -1; } *buf = tmp; *buflen = len; } } if ((res = ei_read_fill_t(fd, *buf, len, ms)) != len) { erl_errno = (res == -2) ? ETIMEDOUT : EIO; return -1; } return len; }
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; }
/* 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; }
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; }
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; }