Beispiel #1
0
static nif_term_t
salt_box(nif_heap_t *hp, int argc, const nif_term_t argv[])
{
	/* salt_box(Plain_text, Nonce, Public_key, Secret_key) -> Cipher_text. */
	nif_bin_t 		pt;
	nif_bin_t 		nc;
	nif_bin_t 		pk;
	nif_bin_t 		sk;
	nif_bin_t 		ct;
	nif_term_t 		raw;
	nif_term_t 		sub;

	if (argc != 4)
		return (BADARG);

	/* Unpack arguments ensuring they're suitably typed. */
	if (! enif_inspect_iolist_as_binary(hp, argv[0], &pt))
		return (BADARG);

	if (! enif_inspect_binary(hp, argv[1], &nc))
		return (BADARG);

	if (! enif_inspect_binary(hp, argv[2], &pk))
		return (BADARG);

	if (! enif_inspect_binary(hp, argv[3], &sk))
		return (BADARG);

	/* Check constraints on size and zero prefixing. */
	if (pt.size < crypto_box_ZEROBYTES || pt.size > SALT_MAX_MESSAGE_SIZE)
		return (BADARG);
	if (memcmp((const void *)pt.data, &salt_box_zerobytes[0], crypto_box_ZEROBYTES) != 0)
		return (BADARG);

	if (nc.size != crypto_box_NONCEBYTES)
		return (BADARG);

	if (pk.size != crypto_box_PUBLICKEYBYTES)
		return (BADARG);

	if (sk.size != crypto_box_SECRETKEYBYTES)
		return (BADARG);

	/* Allocate space for cipher text. NB: Passing ENOMEM as BADARG. */
	if (! enif_alloc_binary(pt.size, &ct))
		return (BADARG);

	/* Perform the crypto, strip leading zeros. */
	(void)crypto_box(ct.data, pt.data, pt.size, nc.data, pk.data, sk.data);

	raw = enif_make_binary(hp, &ct);
	sub = enif_make_sub_binary(hp, raw, crypto_box_BOXZEROBYTES, ct.size - crypto_box_BOXZEROBYTES);

	return (sub);
}
Beispiel #2
0
static nif_term_t
salt_secretbox_open(nif_heap_t *hp, int argc, const nif_term_t argv[])
{
	/* salt_secretbox_open(Cipher_text, Nonce, Secret_key) -> {ok, Plain_text} | forged_or_garbled. */
	nif_bin_t 		ct;
	nif_bin_t 		nc;
	nif_bin_t 		sk;
	nif_bin_t 		pt;
	nif_term_t 		raw;
	nif_term_t 		sub;
	nif_term_t 		tag;

	if (argc != 3)
		return (BADARG);

	/* Unpack arguments ensuring they're suitably typed. */
	if (! enif_inspect_iolist_as_binary(hp, argv[0], &ct))
		return (BADARG);

	if (! enif_inspect_binary(hp, argv[1], &nc))
		return (BADARG);

	if (! enif_inspect_binary(hp, argv[2], &sk))
		return (BADARG);

	/* Check constraints on size and zero prefixing. */
	if (ct.size < crypto_secretbox_BOXZEROBYTES || ct.size > SALT_MAX_MESSAGE_SIZE)
		return (BADARG);
	if (memcmp((const void *)ct.data, &salt_secretbox_boxzerobytes[0], crypto_secretbox_BOXZEROBYTES) != 0)
		return (BADARG);

	if (nc.size != crypto_secretbox_NONCEBYTES)
		return (BADARG);

	if (sk.size != crypto_secretbox_KEYBYTES)
		return (BADARG);

	/* Allocate space for plain text. NB: Passing ENOMEM as BADARG. */
	if (! enif_alloc_binary(ct.size, &pt))
		return (BADARG);

	/* Perform the crypto, strip leading zeros. */
	if (crypto_secretbox_open(pt.data, ct.data, ct.size, nc.data, sk.data) != 0) {
		enif_release_binary(&pt);

		return (enif_make_atom(hp, "forged_or_garbled"));
	}

	raw = enif_make_binary(hp, &pt);
	sub = enif_make_sub_binary(hp, raw, crypto_secretbox_ZEROBYTES, ct.size - crypto_secretbox_ZEROBYTES);
	tag = enif_make_atom(hp, "ok");

	return (enif_make_tuple2(hp, tag, sub));
}
vector<ERL_NIF_TERM> LiberationCoding::doRepair(vector<ERL_NIF_TERM> blockList, vector<int> blockIdList, vector<int> repairList) {

    set<int> availSet(blockIdList.begin(), blockIdList.end());
    if (availSet.size() < (unsigned int)k)
        throw std::invalid_argument("Not Enough Blocks");
    else if (availSet.size() < blockIdList.size()) {
        throw std::invalid_argument("Blocks should be unique");
    }

    size_t blockSize;

    ErlNifBinary blocks[k + m];
    for(size_t i = 0; i < blockIdList.size(); ++i) {
        int blockId = blockIdList[i];
        enif_inspect_binary(env, blockList[i], &blocks[blockId]);
        blockSize = blocks[blockId].size;
    }

    char* dataBlocks[k];
    char* codeBlocks[m];
    int erasures[k + m];
    ErlNifBinary tmpBin;
    enif_alloc_binary(blockSize * (k + m), &tmpBin);
    char* tmpMemory = (char*)tmpBin.data;

    int j = 0;
    for(int i = 0; i < k + m; ++i) {
        i < k ? dataBlocks[i] = tmpMemory + i * blockSize : codeBlocks[i - k] = tmpMemory + i * blockSize;
        if (availSet.count(i) == 0) {
            erasures[j++] = i;
        } else {
            memcpy(tmpMemory + i * blockSize, blocks[i].data, blockSize);
        }
    }
    erasures[j] = -1;

    repairList.push_back(-1);
    int *selected = &repairList[0];
    int *bitmatrix = liberation_coding_bitmatrix(k, w);
    jerasure_schedule_decode_selected_lazy(k, m, w, bitmatrix, erasures, selected, dataBlocks, codeBlocks, blockSize, blockSize / w, 0);

    vector<ERL_NIF_TERM> repairBlocks;
    int repairId;
    ERL_NIF_TERM allBlocksBin = enif_make_binary(env, &tmpBin);
    for(size_t i = 0; i < repairList.size() - 1; ++i) {
        repairId = repairList[i];
        ERL_NIF_TERM block = enif_make_sub_binary(env, allBlocksBin, repairId * blockSize, blockSize);
        repairBlocks.push_back(block);
    }

    free(bitmatrix);
    return repairBlocks;
}
Beispiel #4
0
static nif_term_t
salt_box_afternm(nif_heap_t *hp, int argc, const nif_term_t argv[])
{
	/* salt_box_afternm(Plain_text, Nonce, Context) -> Cipher_text. */
	nif_bin_t 		pt;
	nif_bin_t 		nc;
	nif_bin_t 		bn;
	nif_bin_t 		ct;
	nif_term_t 		raw;
	nif_term_t 		sub;

	if (argc != 3)
		return (BADARG);

	/* Unpack arguments ensuring they're suitably typed. */
	if (! enif_inspect_iolist_as_binary(hp, argv[0], &pt))
		return (BADARG);

	if (! enif_inspect_binary(hp, argv[1], &nc))
		return (BADARG);

	if (! enif_inspect_binary(hp, argv[2], &bn))
		return (BADARG);

	/* Check constraints on size and zero prefixing. */
	if (pt.size < crypto_box_ZEROBYTES || pt.size > SALT_MAX_MESSAGE_SIZE)
		return (BADARG);
	if (memcmp((const void *)pt.data, &salt_box_zerobytes[0], crypto_box_ZEROBYTES) != 0)
		return (BADARG);

	if (nc.size != crypto_box_NONCEBYTES)
		return (BADARG);

	if (bn.size != crypto_box_BEFORENMBYTES)
		return (BADARG);

	/* Allocate space for precomputed context. NB: Passing ENOMEM as BADARG. */
	if (! enif_alloc_binary(pt.size, &ct))
		return (BADARG);

	/* Perform the crypto, strip leading zeros. */
	(void)crypto_box_afternm(ct.data, pt.data, pt.size, nc.data, bn.data);

	raw = enif_make_binary(hp, &ct);
	sub = enif_make_sub_binary(hp, raw, crypto_box_BOXZEROBYTES, ct.size - crypto_box_BOXZEROBYTES);

	return (sub);
}
Beispiel #5
0
static nif_term_t
salt_sign_open(nif_heap_t *hp, int argc, const nif_term_t argv[])
{
	/* salt_sign_open(Signed_msg, Public_key) -> {ok, Verified_msg} | forged_or_garbled. */
	unsigned long long 	len;
	nif_bin_t 		sm;
	nif_bin_t 		pk;
	nif_bin_t 		pm;
	nif_term_t 		raw;
	nif_term_t 		sub;
	nif_term_t 		tag;

	if (argc != 2)
		return (BADARG);

	/* Unpack arguments ensuring they're suitably typed. */
	if (! enif_inspect_iolist_as_binary(hp, argv[0], &sm))
		return (BADARG);

	if (! enif_inspect_binary(hp, argv[1], &pk))
		return (BADARG);

	/* Check constraints on size. */
	if (sm.size < 1 || sm.size > SALT_MAX_MESSAGE_SIZE)
		return (BADARG);

	if (pk.size != crypto_sign_PUBLICKEYBYTES)
		return (BADARG);

	/* Perform the crypto, potentially adjust signed message size. */
	if (! enif_alloc_binary(sm.size + crypto_sign_BYTES, &pm))
		return (BADARG);

	if (crypto_sign_open(pm.data, &len, sm.data, sm.size, pk.data) != 0) {
		enif_release_binary(&pm);

		return (enif_make_atom(hp, "forged_or_garbled"));
	}
	raw = enif_make_binary(hp, &pm);
	tag = enif_make_atom(hp, "ok");

	if (len != sm.size)
		sub = enif_make_sub_binary(hp, raw, 0, len);
	else
		sub = raw;
	return (enif_make_tuple2(hp, tag, sub));
}
Beispiel #6
0
/*-----------------------------------------------------------------------------------------------------------------------*/
static ERL_NIF_TERM binary_to_msg(ErlNifEnv* env, int32_t argc, ERL_NIF_TERM const argv[])
{
   ERL_NIF_TERM parser_res;
   ParserRes* parser = NULL;
   ERL_NIF_TERM res = get_parser(env, argv[0], &parser_res, &parser);
   if (res != ok_atom)
   {
      return res;
   }
   int32_t delimiter = 0;
   if (!enif_get_int(env, argv[1], &delimiter) || delimiter <= 0 || delimiter >= 255)
   {
      return make_error(env, FIX_FAILED, "Wrong delimiter.");
   }
   ErlNifBinary bin;
   if (!enif_inspect_binary(env, argv[2], &bin))
   {
      return make_error(env, FIX_FAILED, "Wrong binary.");
   }
   char const* stop = NULL;
   FIXError* error = NULL;
   pthread_rwlock_wrlock(&parser->lock);
   FIXMsg* fix_msg = fix_parser_str_to_msg(parser->ptr, (char const*)bin.data, bin.size, delimiter, &stop, &error);
   pthread_rwlock_unlock(&parser->lock);
   if (!fix_msg)
   {
      ERL_NIF_TERM ret = make_parser_error(env, fix_error_get_code(error), fix_error_get_text(error));
      fix_error_free(error);
      return ret;
   }
   MsgRes* msg_res = (MsgRes*)enif_alloc_resource(message_res, sizeof(MsgRes));
   msg_res->msg = fix_msg;
   msg_res->lock = &parser->lock;
   ERL_NIF_TERM msg_term = enif_make_resource(env, msg_res);
   enif_release_resource(msg_res);
   uint32_t pos = stop - (char const*)bin.data + 1;
   char const* msgType = fix_msg_get_type(fix_msg);
   return enif_make_tuple3(
         env,
         ok_atom,
         enif_make_tuple3(env,
            msg_atom,
            enif_make_string(env, msgType, ERL_NIF_LATIN1),
            enif_make_tuple2(env, parser_res, msg_term)),
         enif_make_sub_binary(env, argv[2], pos, bin.size - pos));
}
Beispiel #7
0
static ERL_NIF_TERM
mmap_pread(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
  ErlNifBinary bin;
  ERL_NIF_TERM sub;
  unsigned long offset, size;
  
  if(!enif_inspect_binary(env, argv[0], &bin)) {
    return enif_make_badarg(env);
  }
  if(!enif_get_ulong(env, argv[1], &offset)) {
    return enif_make_badarg(env);
  }
  if(!enif_get_ulong(env, argv[2], &size)) {
    return enif_make_badarg(env);
  }
  
  if((sub = enif_make_sub_binary(env, argv[0], offset, size))) {
    return enif_make_tuple2(env, enif_make_atom(env, "ok"), sub);
  }
  return enif_make_ulong(env, 42);
}
Beispiel #8
0
static nif_term_t
salt_sign(nif_heap_t *hp, int argc, const nif_term_t argv[])
{
	/* salt_sign(Message, Secret_key) -> Signed_msg. */
	unsigned long long 	len;
	nif_bin_t 		pm;
	nif_bin_t 		sk;
	nif_bin_t 		sm;
	nif_term_t 		raw;

	if (argc != 2)
		return (BADARG);

	/* Unpack arguments ensuring they're suitably typed. */
	if (! enif_inspect_iolist_as_binary(hp, argv[0], &pm))
		return (BADARG);

	if (! enif_inspect_binary(hp, argv[1], &sk))
		return (BADARG);

	/* Check constraints on size. */
	if (pm.size < 1 || pm.size > SALT_MAX_MESSAGE_SIZE)
		return (BADARG);

	if (sk.size != crypto_sign_SECRETKEYBYTES)
		return (BADARG);

	/* Perform the crypto, potentially adjust signed message size. */
	if (! enif_alloc_binary(pm.size + crypto_sign_BYTES, &sm))
		return (BADARG);

	(void)crypto_sign(sm.data, &len, pm.data, pm.size, sk.data);
	raw = enif_make_binary(hp, &sm);

	if (len != sm.size)
		return (enif_make_sub_binary(hp, raw, 0, len));
	else
		return (raw);
}
Beispiel #9
0
static ERL_NIF_TERM nacl_box_open_padded(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[])
{
  ErlNifBinary padded_ciphertext;
  ErlNifBinary nonce;
  ErlNifBinary pk;
  ErlNifBinary sk;
  ErlNifBinary result;

  if (!enif_inspect_iolist_as_binary(env, argv[0], &padded_ciphertext))
    return enif_make_badarg(env);

  if (!enif_inspect_iolist_as_binary(env, argv[1], &nonce))
    return enif_make_badarg(env);

  if (!enif_inspect_iolist_as_binary(env, argv[2], &pk))
    return enif_make_badarg(env);

  if (!enif_inspect_iolist_as_binary(env, argv[3], &sk))
    return enif_make_badarg(env);

  if (nonce.size != crypto_box_NONCEBYTES) return enif_make_badarg(env);
  if (pk.size != crypto_box_PUBLICKEYBYTES) return enif_make_badarg(env);
  if (sk.size != crypto_box_SECRETKEYBYTES) return enif_make_badarg(env);
  if (padded_ciphertext.size < crypto_box_BOXZEROBYTES) return enif_make_badarg(env);

  if (!enif_alloc_binary(padded_ciphertext.size, &result))
    return nacl_error_tuple(env, "alloc_failed");

  if (crypto_box_open(result.data, padded_ciphertext.data, padded_ciphertext.size,
		      nonce.data, pk.data, sk.data)) {
    return nacl_error_tuple(env, "crypto_failed");
  }

  return enif_make_sub_binary(env,
			      enif_make_binary(env, &result),
			      crypto_box_ZEROBYTES,
			      padded_ciphertext.size - crypto_box_ZEROBYTES);
}
Beispiel #10
0
static ERL_NIF_TERM nacl_secretbox_padded(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[])
{
  ErlNifBinary key;
  ErlNifBinary nonce;
  ErlNifBinary padded_message;
  ErlNifBinary padded_ciphertext;

  if (!enif_inspect_iolist_as_binary(env, argv[0], &padded_message))
    return enif_make_badarg(env);

  if (!enif_inspect_iolist_as_binary(env, argv[1], &nonce))
    return enif_make_badarg(env);

  if (!enif_inspect_iolist_as_binary(env, argv[2], &key))
    return enif_make_badarg(env);

  if (key.size != crypto_secretbox_KEYBYTES) return enif_make_badarg(env);
  if (nonce.size !=  crypto_secretbox_NONCEBYTES) return enif_make_badarg(env);
  if (padded_message.size < crypto_secretbox_ZEROBYTES) return enif_make_badarg(env);

  if (!enif_alloc_binary(padded_message.size, &padded_ciphertext))
    return nacl_error_tuple(env, "alloc_failed");

  crypto_secretbox(
      padded_ciphertext.data, 
      padded_message.data,
      padded_message.size,
      nonce.data,
      key.data
  );

  return enif_make_sub_binary(env,
			      enif_make_binary(env, &padded_ciphertext),
			      crypto_secretbox_BOXZEROBYTES,
			      padded_message.size - crypto_secretbox_BOXZEROBYTES);
}
Beispiel #11
0
int
dec_string(Decoder* d, ERL_NIF_TERM* value)
{
    int has_escape = 0;
    int num_escapes = 0;
    int st;
    int ulen;
    int ui;
    int hi;
    int lo;
    char* chrbuf;
    int chrpos;

    if(d->p[d->i] != '\"') {
        return 0;
    }
    d->i++;

    st = d->i;

    while(d->i < d->len) {
        if(d->u[d->i] < 0x20) {
            return 0;
        } else if(d->p[d->i] == '\"') {
            d->i++;
            goto parse;
        } else if(d->p[d->i] == '\\') {
            if(d->i+1 >= d->len) {
                return 0;
            }
            has_escape = 1;
            num_escapes += 1;
            d->i++;
            switch(d->p[d->i]) {
                case '\"':
                case '\\':
                case '/':
                case 'b':
                case 'f':
                case 'n':
                case 'r':
                case 't':
                    d->i++;
                    break;
                case 'u':
                    hi = 0;
                    lo = 0;
                    d->i++;
                    if(d->i + 4 >= d->len) {
                        return 0;
                    }
                    hi = int_from_hex(&(d->u[d->i]));
                    if(hi < 0) {
                        return 0;
                    }
                    d->i += 4;
                    if(hi >= 0xD800 && hi < 0xDC00) {
                        if(d->i + 6 >= d->len) {
                            return 0;
                        }
                        if(d->p[d->i++] != '\\') {
                            return 0;
                        } else if(d->p[d->i++] != 'u') {
                            return 0;
                        }
                        lo = int_from_hex(&(d->u[d->i]));
                        if(lo < 0) {
                            return 0;
                        }
                        hi = unicode_from_pair(hi, lo);
                        if(hi < 0) {
                            return 0;
                        }
                    }
                    hi = utf8_len(hi);
                    if(hi < 0) {
                        return 0;
                    }
                    if(lo == 0) {
                        num_escapes += 5 - hi;
                    } else {
                        num_escapes += 11 - hi;
                    }
                    break;
                default:
                    return 0;
            }
        } else if(d->u[d->i] < 0x80) {
            d->i++;
        } else {
            ulen = utf8_validate(&(d->u[d->i]), d->len - d->i);
            if(ulen < 0) {
                return 0;
            }
            d->i += ulen;
        }
    }

    // The goto above ensures that we only
    // hit this when a string is not terminated
    // correctly.
    return 0;

parse:
    if(!has_escape) {
        *value = enif_make_sub_binary(d->env, d->arg, st, (d->i - st - 1));
        return 1;
    }

    hi = 0;
    lo = 0;

    ulen = (d->i - 1) - st - num_escapes;
    chrbuf = (char*) enif_make_new_binary(d->env, ulen, value);
    chrpos = 0;
    ui = st;
    while(ui < d->i - 1) {
        if(d->p[ui] != '\\') {
            chrbuf[chrpos++] = d->p[ui++];
            continue;
        }
        ui++;
        switch(d->p[ui]) {
            case '\"':
            case '\\':
            case '/':
                chrbuf[chrpos++] = d->p[ui];
                ui++;
                break;
            case 'b':
                chrbuf[chrpos++] = '\b';
                ui++;
                break;
            case 'f':
                chrbuf[chrpos++] = '\f';
                ui++;
                break;
            case 'n':
                chrbuf[chrpos++] = '\n';
                ui++;
                break;
            case 'r':
                chrbuf[chrpos++] = '\r';
                ui++;
                break;
            case 't':
                chrbuf[chrpos++] = '\t';
                ui++;
                break;
            case 'u':
                ui++;
                hi = int_from_hex(&(d->u[ui]));
                if(hi < 0) {
                    return 0;
                }
                if(hi >= 0xD800 && hi < 0xDC00) {
                    lo = int_from_hex(&(d->u[ui+6]));
                    if(lo < 0) {
                        return 0;
                    }
                    hi = unicode_from_pair(hi, lo);
                    ui += 10;
                } else {
                    ui += 4;
                }
                hi = unicode_to_utf8(hi, (unsigned char*) chrbuf+chrpos);
                if(hi < 0) {
                    return 0;
                }
                chrpos += hi;
                break;
            default:
                return 0;
        }
    }

    return 1;
}
Beispiel #12
0
void emit(parser_data *data, const char *at, size_t length, ERL_NIF_TERM name)
{
    size_t pos = ((void *)at) - ((void *)data->buf_bin->data);
    ERL_NIF_TERM term = enif_make_sub_binary(data->env, data->buf_term, pos, length);
    data->result = enif_make_list_cell(data->env, enif_make_tuple2(data->env, name, term), data->result);
}
Beispiel #13
0
ERL_NIF_TERM
decode_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    Decoder* d;
    jiffy_st* st = (jiffy_st*) enif_priv_data(env);

    ErlNifBinary bin;

    ERL_NIF_TERM objs;
    ERL_NIF_TERM curr;
    ERL_NIF_TERM val = argv[2];
    ERL_NIF_TERM trailer;
    ERL_NIF_TERM ret;
    size_t bytes_read = 0;

    if(argc != 5) {
        return enif_make_badarg(env);
    } else if(!enif_inspect_binary(env, argv[0], &bin)) {
        return enif_make_badarg(env);
    } else if(!enif_get_resource(env, argv[1], st->res_dec, (void**) &d)) {
        return enif_make_badarg(env);
    } else if(!enif_is_list(env, argv[3])) {
        return enif_make_badarg(env);
    } else if(!enif_is_list(env, argv[4])) {
        return enif_make_badarg(env);
    }

    dec_init(d, env, argv[0], &bin);
    objs = argv[3];
    curr = argv[4];

    while(d->i < bin.size) {
        if(should_yield(env, &bytes_read, d->bytes_per_red)) {
            return enif_make_tuple5(
                    env,
                    st->atom_iter,
                    argv[1],
                    val,
                    objs,
                    curr
                );
        }

        bytes_read += 1;

        switch(dec_curr(d)) {
            case st_value:
                switch(d->p[d->i]) {
                    case ' ':
                    case '\n':
                    case '\r':
                    case '\t':
                        d->i++;
                        break;
                    case 'n':
                        if(d->i + 3 >= d->len) {
                            ret = dec_error(d, "invalid_literal");
                            goto done;
                        }
                        if(memcmp(&(d->p[d->i]), "null", 4) != 0) {
                            ret = dec_error(d, "invalid_literal");
                            goto done;
                        }
                        val = d->null_term;
                        dec_pop(d, st_value);
                        d->i += 4;
                        break;
                    case 't':
                        if(d->i + 3 >= d->len) {
                            ret = dec_error(d, "invalid_literal");
                            goto done;
                        }
                        if(memcmp(&(d->p[d->i]), "true", 4) != 0) {
                            ret = dec_error(d, "invalid_literal");
                            goto done;
                        }
                        val = d->atoms->atom_true;
                        dec_pop(d, st_value);
                        d->i += 4;
                        break;
                    case 'f':
                        if(d->i + 4 >= bin.size) {
                            ret = dec_error(d, "invalid_literal");
                            goto done;
                        }
                        if(memcmp(&(d->p[d->i]), "false", 5) != 0) {
                            ret = dec_error(d, "invalid_literal");
                            goto done;
                        }
                        val = d->atoms->atom_false;
                        dec_pop(d, st_value);
                        d->i += 5;
                        break;
                    case '\"':
                        if(!dec_string(d, &val)) {
                            ret = dec_error(d, "invalid_string");
                            goto done;
                        }
                        dec_pop(d, st_value);
                        break;
                    case '-':
                    case '0':
                    case '1':
                    case '2':
                    case '3':
                    case '4':
                    case '5':
                    case '6':
                    case '7':
                    case '8':
                    case '9':
                        if(!dec_number(d, &val)) {
                            ret = dec_error(d, "invalid_number");
                            goto done;
                        }
                        dec_pop(d, st_value);
                        break;
                    case '{':
                        dec_push(d, st_object);
                        dec_push(d, st_key);
                        objs = enif_make_list_cell(env, curr, objs);
                        curr = enif_make_list(env, 0);
                        d->i++;
                        break;
                    case '[':
                        dec_push(d, st_array);
                        dec_push(d, st_value);
                        objs = enif_make_list_cell(env, curr, objs);
                        curr = enif_make_list(env, 0);
                        d->i++;
                        break;
                    case ']':
                        if(!enif_is_empty_list(env, curr)) {
                            ret = dec_error(d, "invalid_json");
                            goto done;
                        }
                        dec_pop(d, st_value);
                        if(dec_curr(d) != st_array) {
                            ret = dec_error(d, "invalid_json");
                            goto done;
                        }
                        dec_pop(d, st_array);
                        dec_pop(d, st_value);
                        val = curr; // curr is []
                        if(!enif_get_list_cell(env, objs, &curr, &objs)) {
                            ret = dec_error(d, "internal_error");
                            goto done;
                        }
                        d->i++;
                        break;
                    default:
                        ret = dec_error(d, "invalid_json");
                        goto done;
                }
                if(dec_top(d) == 0) {
                    dec_push(d, st_done);
                } else if(dec_curr(d) != st_value && dec_curr(d) != st_key) {
                    dec_push(d, st_comma);
                    curr = enif_make_list_cell(env, val, curr);
                }
                break;

            case st_key:
                switch(d->p[d->i]) {
                    case ' ':
                    case '\n':
                    case '\r':
                    case '\t':
                        d->i++;
                        break;
                    case '\"':
                        if(!dec_string(d, &val)) {
                            ret = dec_error(d, "invalid_string");
                            goto done;
                        }
                        dec_pop(d, st_key);
                        dec_push(d, st_colon);
                        curr = enif_make_list_cell(env, val, curr);
                        break;
                    case '}':
                        if(!enif_is_empty_list(env, curr)) {
                            ret = dec_error(d, "invalid_json");
                            goto done;
                        }
                        dec_pop(d, st_key);
                        dec_pop(d, st_object);
                        dec_pop(d, st_value);
                        val = make_empty_object(env, d->return_maps);
                        if(!enif_get_list_cell(env, objs, &curr, &objs)) {
                            ret = dec_error(d, "internal_error");
                            goto done;
                        }
                        if(dec_top(d) == 0) {
                            dec_push(d, st_done);
                        } else {
                            dec_push(d, st_comma);
                            curr = enif_make_list_cell(env, val, curr);
                        }
                        d->i++;
                        break;
                    default:
                        ret = dec_error(d, "invalid_json");
                        goto done;
                }
                break;

            case st_colon:
                switch(d->p[d->i]) {
                    case ' ':
                    case '\n':
                    case '\r':
                    case '\t':
                        d->i++;
                        break;
                    case ':':
                        dec_pop(d, st_colon);
                        dec_push(d, st_value);
                        d->i++;
                        break;
                    default:
                        ret = dec_error(d, "invalid_json");
                        goto done;
                }
                break;

            case st_comma:
                switch(d->p[d->i]) {
                    case ' ':
                    case '\n':
                    case '\r':
                    case '\t':
                        d->i++;
                        break;
                    case ',':
                        dec_pop(d, st_comma);
                        switch(dec_curr(d)) {
                            case st_object:
                                dec_push(d, st_key);
                                break;
                            case st_array:
                                dec_push(d, st_value);
                                break;
                            default:
                                ret = dec_error(d, "internal_error");
                                goto done;
                        }
                        d->i++;
                        break;
                    case '}':
                        dec_pop(d, st_comma);
                        if(dec_curr(d) != st_object) {
                            ret = dec_error(d, "invalid_json");
                            goto done;
                        }
                        dec_pop(d, st_object);
                        dec_pop(d, st_value);
                        if(!make_object(env, curr, &val,
                                d->return_maps, d->dedupe_keys)) {
                            ret = dec_error(d, "internal_object_error");
                            goto done;
                        }
                        if(!enif_get_list_cell(env, objs, &curr, &objs)) {
                            ret = dec_error(d, "internal_error");
                            goto done;
                        }
                        if(dec_top(d) > 0) {
                            dec_push(d, st_comma);
                            curr = enif_make_list_cell(env, val, curr);
                        } else {
                            dec_push(d, st_done);
                        }
                        d->i++;
                        break;
                    case ']':
                        dec_pop(d, st_comma);
                        if(dec_curr(d) != st_array) {
                            ret = dec_error(d, "invalid_json");
                            goto done;
                        }
                        dec_pop(d, st_array);
                        dec_pop(d, st_value);
                        val = make_array(env, curr);
                        if(!enif_get_list_cell(env, objs, &curr, &objs)) {
                            ret = dec_error(d, "internal_error");
                            goto done;
                        }
                        if(dec_top(d) > 0) {
                            dec_push(d, st_comma);
                            curr = enif_make_list_cell(env, val, curr);
                        } else {
                            dec_push(d, st_done);
                        }
                        d->i++;
                        break;
                    default:
                        ret = dec_error(d, "invalid_json");
                        goto done;
                }
                break;

            case st_done:
                switch(d->p[d->i]) {
                    case ' ':
                    case '\n':
                    case '\r':
                    case '\t':
                        d->i++;
                        break;
                    default:
                        goto decode_done;
                }
                break;

            default:
                ret = dec_error(d, "invalid_internal_state");
                goto done;
        }
    }

decode_done:

    if(d->i < bin.size && d->return_trailer) {
        trailer = enif_make_sub_binary(env, argv[0], d->i, bin.size - d->i);
        val = enif_make_tuple3(env, d->atoms->atom_has_trailer, val, trailer);
    } else if(d->i < bin.size) {
        ret = dec_error(d, "invalid_trailing_data");
        goto done;
    }

    if(dec_curr(d) != st_done) {
        ret = dec_error(d, "truncated_json");
    } else if(d->is_partial) {
        ret = enif_make_tuple2(env, d->atoms->atom_partial, val);
    } else {
        ret = val;
    }

done:
    return ret;
}
Beispiel #14
0
ERL_NIF_TERM parse_buffer(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
	Parser par;
	Parser* parser = &par;

	ErlNifBinary buffer;

	if(!enif_inspect_binary(env, argv[0], &buffer)) return enif_make_badarg(env);
	if(!init_parser(parser, env, argv[0], &buffer, argv[1])) return enif_make_badarg(env);

	ERL_NIF_TERM reply = argv[2];
	ERL_NIF_TERM return_value;

	parser->remaining_length = buffer.size;
	parser->pointer = buffer.data + parser->frame_start;

	while (parser->frame_start < parser->buffer_size) {
		
		parser->frame_size = D3I(parser->pointer);

		parser->pointer += 3;
		unsigned long seg_num = D1(parser->pointer);
		parser->pointer += 1;

		parser->remaining_length -= (parser->frame_size + 4);

		if (parser->remaining_length < 0) {
			return_value = enif_make_tuple3(env, 
				parser->atoms->atom_incomplete,
				reply, 
				enif_make_sub_binary(env, parser->raw, parser->frame_start, parser->buffer_size - parser->frame_start));

			break;
		}

		if (*parser->pointer == MYSQL_RESP_EOF) {
			ERL_NIF_TERM remaining_buffer = enif_make_sub_binary(env, parser->raw, parser->frame_start + parser->frame_size + 4, parser->remaining_length);

			if (parser->frame_size == 5) {
				unsigned long server_status = D2I(parser->pointer + 3);

				return_value = enif_make_tuple5(env, 
					parser->atoms->atom_eof,
					enif_make_uint(env, server_status), 
					enif_make_uint(env, seg_num), 
					reply,
					remaining_buffer);
			} 

			else return_value = enif_make_tuple4(env, 
					parser->atoms->atom_eof,
					enif_make_uint(env, seg_num),
					reply,
					remaining_buffer);

			break;

		}

		parser->frame_start += 4;

		ERL_NIF_TERM row = parse_line(parser);
		reply = enif_make_list_cell(env, row, reply);

		parser->frame_start += parser->frame_size;
		parser->pointer += parser->frame_size;
	}

	if (parser->frame_start >= parser->buffer_size) return_value = enif_make_tuple3(env, 
												parser->atoms->atom_incomplete,
												reply, 
												parser->atoms->atom_empty);

	destroy_parser(parser);
	return return_value;
}
ERL_NIF_TERM LiberationCoding::doDecode(vector<ERL_NIF_TERM> blockList, vector<int> blockIdList, size_t dataSize) {

    set<int> availSet(blockIdList.begin(), blockIdList.end());
    if (availSet.size() < (unsigned int)k)
        throw std::invalid_argument("Not Enough Blocks");
    else if (availSet.size() < blockIdList.size()) {
        throw std::invalid_argument("Blocks should be unique");
    }

    size_t blockSize;

    ErlNifBinary blocks[k + m];
    for(size_t i = 0; i < blockIdList.size(); ++i) {
        int blockId = blockIdList[i];
        enif_inspect_binary(env, blockList[i], &blocks[blockId]);
        blockSize = blocks[blockId].size;
    }

    bool needFix = false;

    for(int i = 0; i < k; ++i)
        if (availSet.count(i) == 0) {
            needFix = true;
        }


    if (!needFix) {
        ErlNifBinary file;
        enif_alloc_binary(dataSize, &file);
        size_t copySize, offset = 0;
        for(int i = 0; i < k; ++i) {
            offset = i * blockSize;
            copySize = min(dataSize - offset, blockSize);
            memcpy(file.data + offset, blocks[i].data, copySize);
        }
        ERL_NIF_TERM bin = enif_make_binary(env, &file);
        return bin;
    }

    char* dataBlocks[k];
    char* codeBlocks[m];
    int erasures[k + m];
    ErlNifBinary tmpBin;
    enif_alloc_binary(blockSize * (k + m), &tmpBin);
    char* tmpMemory = (char*)tmpBin.data;

    int j = 0;
    for(int i = 0; i < k + m; ++i) {
        i < k ? dataBlocks[i] = tmpMemory + i * blockSize : codeBlocks[i - k] = tmpMemory + i * blockSize;
        if (availSet.count(i) == 0) {
            erasures[j++] = i;
        } else {
            memcpy(tmpMemory + i * blockSize, blocks[i].data, blockSize);
        }
    }
    erasures[j] = -1;

    int *bitmatrix = liberation_coding_bitmatrix(k, w);
    jerasure_schedule_decode_data_lazy(k, m, w, bitmatrix, erasures, dataBlocks, codeBlocks, blockSize, blockSize / w, 0);

    ERL_NIF_TERM allBlocksBin = enif_make_binary(env, &tmpBin);
    ERL_NIF_TERM bin = enif_make_sub_binary(env, allBlocksBin, 0, dataSize);

    free(bitmatrix);
    return bin;
}
Beispiel #16
0
int
dec_number(Decoder* d, ERL_NIF_TERM* value)
{
    ERL_NIF_TERM num_type = d->atoms->atom_error;
    char state = nst_init;
    char nbuf[NUM_BUF_LEN];
    int st = d->i;
    int has_frac = 0;
    int has_exp = 0;
    double dval;
    long lval;

    while(d->i < d->len) {
        switch(state) {
            case nst_init:
                switch(d->p[d->i]) {
                    case '-':
                        state = nst_sign;
                        d->i++;
                        break;
                    case '0':
                        state = nst_frac0;
                        d->i++;
                        break;
                    case '1':
                    case '2':
                    case '3':
                    case '4':
                    case '5':
                    case '6':
                    case '7':
                    case '8':
                    case '9':
                        state = nst_mantissa;
                        d->i++;
                        break;
                    default:
                        return 0;
                }
                break;

            case nst_sign:
                switch(d->p[d->i]) {
                    case '0':
                        state = nst_frac0;
                        d->i++;
                        break;
                    case '1':
                    case '2':
                    case '3':
                    case '4':
                    case '5':
                    case '6':
                    case '7':
                    case '8':
                    case '9':
                        state = nst_mantissa;
                        d->i++;
                        break;
                    default:
                        return 0;
                }
                break;

            case nst_mantissa:
                switch(d->p[d->i]) {
                    case '.':
                        state = nst_frac1;
                        d->i++;
                        break;
                    case 'e':
                    case 'E':
                        state = nst_esign;
                        d->i++;
                        break;
                    case '0':
                    case '1':
                    case '2':
                    case '3':
                    case '4':
                    case '5':
                    case '6':
                    case '7':
                    case '8':
                    case '9':
                        d->i++;
                        break;
                    default:
                        goto parse;
                }
                break;

            case nst_frac0:
                switch(d->p[d->i]) {
                    case '.':
                        state = nst_frac1;
                        d->i++;
                        break;
                    case 'e':
                    case 'E':
                        state = nst_esign;
                        d->i++;
                        break;
                    default:
                        goto parse;
                }
                break;

            case nst_frac1:
                has_frac = 1;
                switch(d->p[d->i]) {
                    case '0':
                    case '1':
                    case '2':
                    case '3':
                    case '4':
                    case '5':
                    case '6':
                    case '7':
                    case '8':
                    case '9':
                        state = nst_frac;
                        d->i++;
                        break;
                    default:
                        goto parse;
                }
                break;

            case nst_frac:
                switch(d->p[d->i]) {
                    case 'e':
                    case 'E':
                        state = nst_esign;
                        d->i++;
                        break;
                    case '0':
                    case '1':
                    case '2':
                    case '3':
                    case '4':
                    case '5':
                    case '6':
                    case '7':
                    case '8':
                    case '9':
                        d->i++;
                        break;
                    default:
                        goto parse;
                }
                break;

            case nst_esign:
                has_exp = 1;
                switch(d->p[d->i]) {
                    case '-':
                    case '+':
                    case '0':
                    case '1':
                    case '2':
                    case '3':
                    case '4':
                    case '5':
                    case '6':
                    case '7':
                    case '8':
                    case '9':
                        state = nst_edigit;
                        d->i++;
                        break;
                    default:
                        return 0;
                }
                break;

            case nst_edigit:
                switch(d->p[d->i]) {
                    case '0':
                    case '1':
                    case '2':
                    case '3':
                    case '4':
                    case '5':
                    case '6':
                    case '7':
                    case '8':
                    case '9':
                        d->i++;
                        break;
                    default:
                        goto parse;
                }
                break;

            default:
                return 0;
        }
    }

parse:

    switch(state) {
        case nst_init:
        case nst_sign:
        case nst_frac1:
        case nst_esign:
            return 0;
        default:
            break;
    }

    errno = 0;

    if(d->i - st < NUM_BUF_LEN) {
        memset(nbuf, 0, NUM_BUF_LEN);
        memcpy(nbuf, &(d->p[st]), d->i - st);

        if(has_frac || has_exp) {
            dval = strtod(nbuf, NULL);
            if(errno != ERANGE) {
                *value = enif_make_double(d->env, dval);
                return 1;
            }
        } else {
            lval = strtol(nbuf, NULL, 10);
            if(errno != ERANGE) {
                *value = enif_make_int64(d->env, lval);
                return 1;
            }
        }
    }

    if(!has_frac && !has_exp) {
        num_type = d->atoms->atom_bignum;
    } else if(!has_frac && has_exp) {
        num_type = d->atoms->atom_bignum_e;
    } else {
        num_type = d->atoms->atom_bigdbl;
    }

    d->is_partial = 1;
    *value = enif_make_sub_binary(d->env, d->arg, st, d->i - st);
    *value = enif_make_tuple2(d->env, num_type, *value);
    return 1;
}
Beispiel #17
0
ERL_NIF_TERM parse_line(Parser* parser) {
	unsigned long idx = parser->frame_start;
	unsigned col = 0;
	
	ERL_NIF_TERM reply[parser->table_width];

	while(col < parser->table_width) {

		unsigned char size_length = (parser->buffer[idx] <= MYSQL_LIMIT_BYTE) ? (1) : (parser->buffer[idx] - MYSQL_LIMIT_BYTE);
		size_length *= (size_length == 4) ? (2) : (1);

		unsigned long long content_length = 0; 
		if (parser->buffer[idx] != MYSQL_NULL_RESULT) {
			switch (size_length) {
				case 1:
					content_length = D1(parser->buffer + idx);
					break;
				case 2:
					content_length = D2I(parser->buffer + idx + 1);
					size_length++;
					break;
				case 3:
					content_length = D3I(parser->buffer + idx + 1);
					size_length++;
					break;
				case 8:
					content_length =  D8I(parser->buffer + idx + 1);
					size_length++;
					break;
			}
		} else content_length = 0;

		unsigned char *new_val = parser->buffer + idx + size_length;
		MYSQL_TIME time_;

		if (content_length == 0) reply[col] = parser->atoms->atom_undefined;
		else if (parser->columns[col] == MYSQL_TYPE_BIT
			|| parser->columns[col] == MYSQL_TYPE_TINY_BLOB
			|| parser->columns[col] == MYSQL_TYPE_MEDIUM_BLOB
			|| parser->columns[col] == MYSQL_TYPE_LONG_BLOB
			|| parser->columns[col] == MYSQL_TYPE_BLOB
			|| parser->columns[col] == MYSQL_TYPE_VAR_STRING
			|| parser->columns[col] == MYSQL_TYPE_STRING) reply[col] = enif_make_sub_binary(parser->env, parser->raw, idx + size_length, size_length + content_length - 1);
		else if (parser->columns[col] == MYSQL_TYPE_TINY
			|| parser->columns[col] == MYSQL_TYPE_SHORT
			|| parser->columns[col] == MYSQL_TYPE_LONG
			|| parser->columns[col] == MYSQL_TYPE_LONGLONG
			|| parser->columns[col] == MYSQL_TYPE_INT24
			|| parser->columns[col] == MYSQL_TYPE_YEAR) reply[col] = enif_make_int(parser->env, atoi((char *) new_val));
		else if (parser->columns[col] == MYSQL_TYPE_DECIMAL
			|| parser->columns[col] == MYSQL_TYPE_NEWDECIMAL
			|| parser->columns[col] == MYSQL_TYPE_FLOAT
			|| parser->columns[col] == MYSQL_TYPE_DOUBLE) reply[col] = enif_make_double(parser->env, strtod((const char *) new_val, NULL));
		else if (parser->columns[col] == MYSQL_TYPE_DATE) {
			sscanf((const char*) new_val, "%d-%d-%d", &time_.year, &time_.month, &time_.day);

			reply[col] = enif_make_tuple2(parser->env,
        		parser->atoms->atom_date,
				enif_make_tuple3(parser->env, 
		            enif_make_int(parser->env, time_.year),
		            enif_make_int(parser->env, time_.month),
		            enif_make_int(parser->env, time_.day))
				);
		}
		else if (parser->columns[col] == MYSQL_TYPE_TIME) {
			sscanf((const char*) new_val, "%d:%d:%d", &time_.hour, &time_.minute, &time_.second);

            reply[col] = enif_make_tuple2(parser->env,
        		parser->atoms->atom_time,
        		enif_make_tuple3(parser->env, 
		            enif_make_int(parser->env, time_.hour),
		            enif_make_int(parser->env, time_.minute),
		            enif_make_int(parser->env, time_.second))
        		);
		}
		else if (parser->columns[col] == MYSQL_TYPE_TIMESTAMP
			|| parser->columns[col] == MYSQL_TYPE_DATETIME) {
			sscanf((const char*) new_val, "%d-%d-%d %d:%d:%d", &time_.year, &time_.month, &time_.day, &time_.hour, &time_.minute, &time_.second);

            reply[col] = enif_make_tuple2(parser->env,
        		parser->atoms->atom_datetime,
            	enif_make_tuple2(parser->env,
					enif_make_tuple3(parser->env, 
						enif_make_int(parser->env, time_.year),
						enif_make_int(parser->env, time_.month),
						enif_make_int(parser->env, time_.day)
					),
					enif_make_tuple3(parser->env,
						enif_make_int(parser->env, time_.hour),
						enif_make_int(parser->env, time_.minute),
						enif_make_int(parser->env, time_.second)
					)
				)
			);

		}
		else if (parser->columns[col] == MYSQL_TYPE_FIELD_EXTRA) {
			ERL_NIF_TERM default_content;
			if (content_length > 12) default_content = enif_make_sub_binary(parser->env, parser->raw, idx + size_length + 12, size_length + content_length - 13);
			else default_content = parser->atoms->atom_undefined;

			reply[col] = enif_make_tuple6(parser->env,
				enif_make_int(parser->env, D2I(new_val)),
				enif_make_int(parser->env, D4I(new_val + 2)),
				enif_make_int(parser->env, D1(new_val + 6)),
				enif_make_int(parser->env, D2I(new_val + 7)),
				enif_make_int(parser->env, D1(new_val + 11)),
				default_content
			);
		}

		col++;
		idx += content_length + size_length;

	}

	return enif_make_list_from_array(parser->env, reply, parser->table_width);

}