static ERL_NIF_TERM open_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { posix_errno_t posix_errno; efile_data_t *d; ErlNifPid controlling_process; enum efile_modes_t modes; ERL_NIF_TERM result; efile_path_t path; if(argc != 2 || !enif_is_list(env, argv[1])) { return enif_make_badarg(env); } modes = efile_translate_modelist(env, argv[1]); if((posix_errno = efile_marshal_path(env, argv[0], &path))) { return posix_error_to_tuple(env, posix_errno); } else if((posix_errno = efile_open(&path, modes, efile_resource_type, &d))) { return posix_error_to_tuple(env, posix_errno); } result = enif_make_resource(env, d); enif_release_resource(d); enif_self(env, &controlling_process); if(enif_monitor_process(env, d, &controlling_process, &d->monitor)) { return posix_error_to_tuple(env, EINVAL); } return enif_make_tuple2(env, am_ok, result); }
static ERL_NIF_TERM send_list_seq(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifPid to; ERL_NIF_TERM msg; ErlNifEnv* msg_env; int i, res; if (!enif_get_int(env, argv[0], &i)) { return enif_make_badarg(env); } if (argv[1] == atom_self) { enif_self(env, &to); } else if (!enif_get_local_pid(env, argv[1], &to)) { return enif_make_badarg(env); } msg_env = enif_alloc_env(); msg = enif_make_list(msg_env,0); for ( ; i>0 ; i--) { msg = enif_make_list_cell(msg_env, enif_make_int(msg_env, i), msg); } res = enif_send(env, &to, msg_env, msg); enif_free_env(msg_env); return enif_make_tuple2(env, atom_ok, enif_make_int(env,res)); }
static ERL_NIF_TERM send_to_self(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { state_t* state = (state_t*) enif_priv_data(env); ErlNifPid* pid = (ErlNifPid*) enif_alloc(sizeof(ErlNifPid)); enif_self(env, pid); queue_push(state->queue, pid); return state->atom_ok; }
static ERL_NIF_TERM open_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { posix_errno_t posix_errno; efile_data_t *d; ErlNifPid controlling_process; enum efile_modes_t modes; ERL_NIF_TERM result; efile_path_t path; ASSERT(argc == 2); if(!enif_is_list(env, argv[1])) { return enif_make_badarg(env); } modes = efile_translate_modelist(env, argv[1]); if((posix_errno = efile_marshal_path(env, argv[0], &path))) { return posix_error_to_tuple(env, posix_errno); } else if((posix_errno = efile_open(&path, modes, efile_resource_type, &d))) { return posix_error_to_tuple(env, posix_errno); } enif_self(env, &controlling_process); if(enif_monitor_process(env, d, &controlling_process, &d->monitor)) { /* We need to close the file manually as we haven't registered a * destructor. */ posix_errno_t ignored; erts_atomic32_set_acqb(&d->state, EFILE_STATE_CLOSED); efile_close(d, &ignored); return posix_error_to_tuple(env, EINVAL); } /* Note that we do not call enif_release_resource at this point. While it's * normally safe to leave resource management to the GC, efile_close is a * blocking operation which must not be done in the GC callback, and we * can't defer it as the resource is gone as soon as it returns. * * We instead keep the resource alive until efile_close is called, after * which it's safe to leave things to the GC. If the controlling process * were to die before the user had a chance to close their file, the above * monitor will tell the erts_prim_file process to close it for them. */ result = enif_make_resource(env, d); return enif_make_tuple2(env, am_ok, result); }
ERL_NIF_TERM nif_thread_call(ErlNifEnv* env, ERL_NIF_TERM (*f)(ErlNifEnv*, nif_thread_arg*), int a, ...) { va_list ap; int i; nif_thread_arg* args = (nif_thread_arg*)enif_alloc(a * sizeof(nif_thread_arg)); va_start(ap, a); for (i = 0; i < a; i++) args[i] = va_arg(ap, void*); va_end(ap); ErlNifPid* pid = (ErlNifPid*)enif_alloc(sizeof(ErlNifPid)); nif_thread_message* msg = nif_thread_message_alloc((void*)f, args, enif_self(env, pid)); return nif_thread_send((nif_thread_state*)enif_priv_data(env), msg); }
static ERL_NIF_TERM send(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifEnv* cp_env = enif_alloc_env(); ErlNifPid dst; ERL_NIF_TERM msg; ERL_NIF_TERM ret; if(argc == 1) { if(!enif_self(env, &dst)) { ret = enif_make_badarg(env); goto done; } msg = argv[0]; } else if(argc == 2) { if(!enif_get_local_pid(env, argv[0], &dst)) { ret = enif_make_badarg(env); goto done; } msg = argv[1]; } else { ret = enif_make_badarg(env); goto done; } msg = enif_make_copy(cp_env, msg); if(!enif_send(env, &dst, cp_env, msg)) { ret = enif_make_badarg(env); goto done; } ret = enif_make_atom(env, "ok"); done: enif_free_env(cp_env); return ret; }
static ERL_NIF_TERM dirty_call_while_terminated_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifPid self; ERL_NIF_TERM result, self_term; ErlNifPid to; ErlNifEnv* menv; int res; if (!enif_get_local_pid(env, argv[0], &to)) return enif_make_badarg(env); if (!enif_self(env, &self)) return enif_make_badarg(env); self_term = enif_make_pid(env, &self); menv = enif_alloc_env(); result = enif_make_tuple2(menv, enif_make_atom(menv, "dirty_alive"), self_term); res = enif_send(env, &to, menv, result); enif_free_env(menv); if (!res) return enif_make_badarg(env); /* Wait until we have been killed */ while (enif_is_process_alive(env, &self)) ; result = enif_make_tuple2(env, enif_make_atom(env, "dirty_dead"), self_term); res = enif_send(env, &to, NULL, result); #ifdef __WIN32__ Sleep(1000); #else sleep(1); #endif return enif_make_atom(env, "ok"); }
static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { int state_arity; ErlNifPid self, to; ERL_NIF_TERM *tuple, msg; ASSERT(argc == 5); tuple = enif_alloc(sizeof(ERL_NIF_TERM)*(argc+1)); memcpy(tuple+1,argv,sizeof(ERL_NIF_TERM)*argc); if (enif_self(env, &self)) { tuple[0] = enif_make_pid(env, &self); } else { tuple[0] = enif_make_atom(env, "undefined"); } msg = enif_make_tuple_from_array(env, tuple, argc + 1); enif_get_local_pid(env, argv[1], &to); enif_send(env, &to, NULL, msg); enif_free(tuple); return atom_ok; }
static ERL_NIF_TERM alsa_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { int sample_rate, channels; int selected_device = -1; enif_get_int(env, argv[0], &sample_rate); enif_get_int(env, argv[1], &channels); if(argc > 2) { enif_get_int(env, argv[2], &selected_device); } // selectedDevice = dump_audio_info(selectedDevice); AudioCapture *capture = (AudioCapture *)enif_alloc_resource(alsa_resource, sizeof(AudioCapture)); bzero(capture, sizeof(AudioCapture)); capture->sample_rate = sample_rate; capture->channels = channels; capture->frame_size = capture->channels*2*1024; capture->selected_device = selected_device; enif_self(env, &capture->owner_pid); capture->env = enif_alloc_env(); fprintf(stderr, "Starting alsa %d\r\n", capture->sample_rate); capture->thread_started = 1; enif_thread_create("alsa_thread", &capture->tid, capture_thread, capture, NULL); ERL_NIF_TERM port = enif_make_resource(env, capture); capture->port = enif_make_copy(capture->env, port); enif_release_resource(capture); return port; }
static ERL_NIF_TERM nif_pcap_open_live(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary device = {0}; int snaplen = 0; int promisc = 0; int to_ms = 0; char errbuf[PCAP_ERRBUF_SIZE] = {0}; EWPCAP_STATE *ep = NULL; ERL_NIF_TERM res = {0}; ERL_NIF_TERM ref = {0}; if (!enif_inspect_iolist_as_binary(env, argv[0], &device)) return enif_make_badarg(env); if (!enif_get_int(env, argv[1], &snaplen)) return enif_make_badarg(env); if (!enif_get_int(env, argv[2], &promisc)) return enif_make_badarg(env); if (!enif_get_int(env, argv[3], &to_ms)) return enif_make_badarg(env); /* NULL terminate the device name */ if (device.size > 0 && !enif_realloc_binary(&device, device.size+1)) return enif_make_tuple2(env, atom_error, atom_enomem); device.data[device.size-1] = '\0'; ep = enif_alloc_resource(EWPCAP_RESOURCE, sizeof(EWPCAP_STATE)); if (ep == NULL) return enif_make_tuple2(env, atom_error, atom_enomem); /* "any" is a Linux only virtual dev */ ep->p = pcap_open_live((device.size == 0 ? "any" : (char *)device.data), snaplen, promisc, to_ms, errbuf); if (ep->p == NULL) return enif_make_tuple2(env, atom_error, enif_make_string(env, errbuf, ERL_NIF_LATIN1)); ep->datalink = pcap_datalink(ep->p); (void)enif_self(env, &ep->pid); ep->term_env = enif_alloc_env(); if (ep->term_env == NULL) { pcap_close(ep->p); return enif_make_tuple2(env, atom_error, atom_enomem); } ep->ref = enif_make_ref(ep->term_env); ref = enif_make_copy(env, ep->ref); res = enif_make_resource(env, ep); enif_release_resource(ep); return enif_make_tuple2(env, atom_ok, enif_make_tuple3(env, atom_ewpcap_resource, ref, res)); }
static ERL_NIF_TERM nif_pcap_open_live(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary device = {0}; int snaplen = 0; int promisc = 0; int to_ms = 0; int buffer_size = 0; int rfmon = 0; char errbuf[PCAP_ERRBUF_SIZE] = {0}; EWPCAP_STATE *ep = NULL; ERL_NIF_TERM res = {0}; ERL_NIF_TERM ref = {0}; if (!enif_inspect_iolist_as_binary(env, argv[0], &device)) return enif_make_badarg(env); if (!enif_get_int(env, argv[1], &snaplen)) return enif_make_badarg(env); if (!enif_get_int(env, argv[2], &promisc)) return enif_make_badarg(env); if (!enif_get_int(env, argv[3], &to_ms)) return enif_make_badarg(env); if (!enif_get_int(env, argv[4], &buffer_size)) return enif_make_badarg(env); if (!enif_get_int(env, argv[5], &rfmon)) return enif_make_badarg(env); /* NULL terminate the device name */ if (device.size > 0) { if (!enif_realloc_binary(&device, device.size+1)) return enif_make_tuple2(env, atom_error, atom_enomem); device.data[device.size-1] = '\0'; } ep = enif_alloc_resource(EWPCAP_RESOURCE, sizeof(EWPCAP_STATE)); if (ep == NULL) return enif_make_tuple2(env, atom_error, atom_enomem); /* "any" is a Linux only virtual dev */ ep->p = pcap_create((device.size == 0 ? "any" : (char *)device.data), errbuf); if (ep->p == NULL) return enif_make_tuple2(env, atom_error, enif_make_string(env, errbuf, ERL_NIF_LATIN1)); /* Set the snaplen */ (void)pcap_set_snaplen(ep->p, snaplen); /* Set promiscuous mode */ (void)pcap_set_promisc(ep->p, promisc); /* Set timeout */ (void)pcap_set_timeout(ep->p, to_ms); /* Set buffer size */ if (buffer_size > 0) (void)pcap_set_buffer_size(ep->p, buffer_size); /* Set monitor mode */ if (pcap_can_set_rfmon(ep->p) == 1) (void)pcap_set_rfmon(ep->p, rfmon); /* Return failure on error and warnings */ if (pcap_activate(ep->p) != 0) { pcap_close(ep->p); return enif_make_tuple2(env, atom_error, enif_make_string(env, pcap_geterr(ep->p), ERL_NIF_LATIN1)); } ep->datalink = pcap_datalink(ep->p); (void)enif_self(env, &ep->pid); ep->term_env = enif_alloc_env(); if (ep->term_env == NULL) { pcap_close(ep->p); return enif_make_tuple2(env, atom_error, atom_enomem); } ep->ref = enif_make_ref(ep->term_env); ref = enif_make_copy(env, ep->ref); res = enif_make_resource(env, ep); enif_release_resource(ep); return enif_make_tuple2(env, atom_ok, enif_make_tuple3(env, atom_ewpcap_resource, ref, res)); }
static ERL_NIF_TERM make_term_caller_pid(struct make_term_info* mti, int n) { ErlNifPid pid; return enif_make_pid(mti->dst_env, enif_self(mti->caller_env, &pid)); }