Пример #1
0
ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, char *buf,
		     ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen)
{
    switch (command) {
    case 'B': /* busy */
	set_busy_port((ErlDrvPort) drv_data, 1);
	break;
    case 'N': /* not busy */
	set_busy_port((ErlDrvPort) drv_data, 0);
	break;
    default:
	driver_failure_posix((ErlDrvPort) drv_data, EINVAL);
	break;
    }
    return 0;
}
Пример #2
0
static int control_control(ErlDrvData port, unsigned command, char* buf, int count,
			   char** res, int res_size)
{
    switch (command) {
    case 'e':
	if (count > res_size) {
	    *res = (char *) driver_alloc(count);
	}
	memcpy(*res, buf, count);
	return count;
    case 'b':
	set_busy_port(erlang_port, buf[0]);
	return 0;
    case 'i':
	driver_output(erlang_port, buf, count);
	return 0;
    default:
	if (command < 256) {
	    return -1;
	} else {
	    char* p = *res;
	    int i;

	    for (i = 3; i >= 0; i--) {
		p[i] = command;
		command >>= 8;
	    }
	    return 4;
	}
    }
}
Пример #3
0
void gen_http_drv_schedule_write(ErlDrvData handle, ErlIOVec *ev)
{
  HTTP* d = (HTTP *)handle;
  driver_enqv(d->port, ev, 0);
  //fprintf(stderr, "Queue %d bytes, %d\r\n", ev->size,  driver_sizeq(d->port));
  activate_write(d);
  if(driver_sizeq(d->port) > d->buffer_limit) {
    set_busy_port(d->port, 1);
  }
}
Пример #4
0
void gen_http_drv_ready_output(ErlDrvData handle, ErlDrvEvent event)
{
  HTTP* d = (HTTP*) handle;
  
  if(d->mode == REQUEST_MODE && d->state == CONNECTING_STATE) {
    accept_connection(d);
    return;
  }
  
  
  SysIOVec* vec;
  int vlen = 0;
  size_t written;
  
  vec = driver_peekq(d->port, &vlen);
  if(!vec || !vlen) {
    deactivate_write(d);
    return;
  }
  written = writev(d->socket, (const struct iovec *)vec, vlen > IOV_MAX ? IOV_MAX : vlen);
  if(vlen > IOV_MAX) {
    fprintf(stderr, "Buffer overloaded: %d, %d\r\n", vlen, (int)(driver_sizeq(d->port) - written));
  }
  if(written == -1) {
    if((errno != EWOULDBLOCK) && (errno != EINTR) && (errno != EAGAIN)) {
        // fprintf(stderr, "Error in writev: %s, %d bytes left\r\n", strerror(errno), (int)driver_sizeq(d->port));
      tcp_exit(d);
      return;
    }
  } else {
    ErlDrvSizeT rest = driver_deq(d->port, written);
    
    if(rest == 0) {
      ErlDrvTermData reply[] = {
        ERL_DRV_ATOM, atom_http,
        ERL_DRV_PORT, driver_mk_port(d->port),
        ERL_DRV_ATOM, atom_empty,
        ERL_DRV_TUPLE, 3
      };
      
      pid_list_send(d->exhausted, d->port, reply, sizeof(reply) / sizeof(reply[0]));
      pid_list_free(&d->exhausted);
      
      set_busy_port(d->port, 0);
    }
    // fprintf(stderr, "Network write: %d (%d)\r\n", (int)written, (int)rest);
    
  }
}
Пример #5
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);
}