static int enm_do_send(EnmData* d, const struct nn_msghdr* msghdr, int* err) { int rc; if (msghdr->msg_iovlen == 0) return 0; *err = 0; do { rc = nn_sendmsg(d->fd, msghdr, NN_DONTWAIT); if (rc < 0) { *err = errno; switch (*err) { case EINTR: case EFSM: /* do nothing */ break; case EAGAIN: d->b.writable = 0; break; default: enm_write_select(d, 0); enm_read_select(d, 0); driver_failure(d->port, *err); } } } while (*err == EINTR); return rc; }
static void failure_drv_output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) { FailureDrvData *data_p = (FailureDrvData *) drv_data; void *void_ptr; ErlDrvPort port = void_ptr = data_p; #ifdef __WIN32__ Sleep(3000); #else sleep(3); #endif driver_failure(port, 0); }
static void enm_outputv(ErlDrvData drv_data, ErlIOVec *ev) { EnmData* d = (EnmData*)drv_data; ErlIOVec qev; ErlDrvSizeT qtotal; struct nn_msghdr msghdr; int i, rc = -1, err; if (d->fd == -1 || d->protocol == NN_PULL || d->protocol == NN_SUB) return; qtotal = driver_peekqv(d->port, &qev); if (qtotal > 0) { memset(&msghdr, 0, sizeof msghdr); msghdr.msg_iov = (struct nn_iovec*)qev.iov; msghdr.msg_iovlen = qev.vsize; msghdr.msg_control = 0; err = 0; do { rc = enm_do_send(d, &msghdr, &err); if (rc < 0) { if (err == EAGAIN) { d->b.writable = 0; break; } else if (err != EINTR) { char errstr[32]; switch (enm_errno_str(err, errstr)) { case ENM_NANOMSG_ERROR: driver_failure_atom(d->port, errstr); break; case ENM_POSIX_ERROR: driver_failure_posix(d->port, err); break; case ENM_UNKNOWN_ERROR: driver_failure(d->port, err); break; } return; } } } while (err == EINTR); } /* * Do nothing if the message has no data */ if (ev->size == 0 || ev->vsize == 0 || (ev->vsize == 1 && *ev->binv == 0 && ev->iov->iov_len == 0)) return; if (d->b.writable) { memset(&msghdr, 0, sizeof msghdr); msghdr.msg_iov = (struct nn_iovec*)ev->iov; msghdr.msg_iovlen = ev->vsize; msghdr.msg_control = 0; err = 0; do { rc = enm_do_send(d, &msghdr, &err); if (rc < 0) { if (err == EAGAIN) { d->b.writable = 0; break; } else if (err != EINTR) { char errstr[32]; switch (enm_errno_str(err, errstr)) { case ENM_NANOMSG_ERROR: driver_failure_atom(d->port, errstr); break; case ENM_POSIX_ERROR: driver_failure_posix(d->port, err); break; case ENM_UNKNOWN_ERROR: driver_failure(d->port, err); break; } return; } } } while (err == EINTR); } if (rc < 0 && !d->b.writable) { rc = 0; d->b.busy = 1; set_busy_port(d->port, d->b.busy); for (i = 0; i < ev->vsize; i++) { ErlDrvBinary* bin = 0; if (ev->binv[i] != 0) { bin = ev->binv[i]; driver_binary_inc_refc(bin); } else if (ev->iov[i].iov_len > 0) { SysIOVec* vec = &ev->iov[i]; bin = driver_alloc_binary(vec->iov_len); memcpy(bin->orig_bytes, vec->iov_base, vec->iov_len); } if (bin != 0) driver_enq_bin(d->port, bin, 0, bin->orig_size); } if (!d->b.write_poll) enm_write_select(d, 1); } if (rc > 0 && d->protocol == NN_SURVEYOR && d->b.active != ENM_FALSE) enm_read_select(d, 1); }
static void echo_drv_output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) { EchoDrvData* data_p = (EchoDrvData *) drv_data; ErlDrvPort port = data_p->erlang_port; switch (buf[0]) { case ECHO_DRV_OUTPUT: { driver_output(port, buf+1, len-1); break; } case ECHO_DRV_OUTPUT2: { driver_output2(port, "a", 1, buf+1, len-1); break; } case ECHO_DRV_OUTPUT_BINARY: { ErlDrvBinary *bin = driver_alloc_binary(len-1); memcpy(&bin->orig_bytes, buf+1, len-1); driver_output_binary(port, "a", 1, bin, 1, len - 2); driver_free_binary(bin); break; } case ECHO_DRV_OUTPUTV: { ErlIOVec iov; ErlDrvSizeT sz; driver_enq(port, buf + 1, len - 1); sz = driver_peekqv(port, &iov); driver_outputv(port, "a", 1, &iov, 0); driver_deq(port, sz); break; } case ECHO_DRV_SET_TIMER: { driver_set_timer(port, 10); break; } case ECHO_DRV_FAILURE_EOF: { driver_failure_eof(port); break; } case ECHO_DRV_FAILURE_ATOM: { driver_failure_atom(port, buf+1); break; } case ECHO_DRV_FAILURE_POSIX: { driver_failure_posix(port, EAGAIN); break; } case ECHO_DRV_FAILURE: { driver_failure(port, buf[1]); break; } case ECHO_DRV_OUTPUT_TERM: case ECHO_DRV_DRIVER_OUTPUT_TERM: case ECHO_DRV_SEND_TERM: case ECHO_DRV_DRIVER_SEND_TERM: { ErlDrvTermData term[] = { ERL_DRV_ATOM, driver_mk_atom("echo"), ERL_DRV_PORT, driver_mk_port(port), ERL_DRV_BUF2BINARY, (ErlDrvTermData)(buf+1), (ErlDrvTermData)(len - 1), ERL_DRV_TUPLE, 3}; switch (buf[0]) { case ECHO_DRV_OUTPUT_TERM: erl_drv_output_term(driver_mk_port(port), term, sizeof(term) / sizeof(ErlDrvTermData)); break; case ECHO_DRV_DRIVER_OUTPUT_TERM: driver_output_term(port, term, sizeof(term) / sizeof(ErlDrvTermData)); break; case ECHO_DRV_SEND_TERM: driver_send_term(port, data_p->caller, term, sizeof(term) / sizeof(ErlDrvTermData)); break; case ECHO_DRV_DRIVER_SEND_TERM: erl_drv_send_term(driver_mk_port(port), data_p->caller, term, sizeof(term) / sizeof(ErlDrvTermData)); break; } break; } case ECHO_DRV_SAVE_CALLER: data_p->caller = driver_caller(port); break; default: break; } }