예제 #1
0
파일: zlib_drv.c 프로젝트: Airon2014/otp
static int zlib_inflate(ZLibData* d, int flush)
{
    int res = Z_OK;

    if ((d->bin == NULL) && (zlib_output_init(d) < 0)) {
	errno = ENOMEM;
	return Z_ERRNO;
    }

    while ((driver_sizeq(d->port) > 0) && (res != Z_STREAM_END)) {
	int vlen;
	SysIOVec* iov = driver_peekq(d->port, &vlen);
	int len;
	int possibly_more_output = 0;

	d->s.next_in = iov[0].iov_base;
	d->s.avail_in = iov[0].iov_len;
	while((possibly_more_output || (d->s.avail_in > 0)) && (res != Z_STREAM_END)) {
	    res = inflate(&d->s, Z_NO_FLUSH);
	    if (res == Z_NEED_DICT) {
		/* Essential to eat the header bytes that zlib has looked at */
		len = iov[0].iov_len - d->s.avail_in;
		driver_deq(d->port, len);
		return res;
	    }
	    if (res == Z_BUF_ERROR) {
		/* Was possible more output, but actually not */
		res = Z_OK;
	    }
	    else if (res < 0) {
		return res;
	    }
	    if (d->s.avail_out != 0) {
		possibly_more_output = 0;
	    } else {
		if (d->want_crc)
		    d->crc = crc32(d->crc, (unsigned char*)d->bin->orig_bytes,
				   d->binsz - d->s.avail_out);
		zlib_output(d);
		possibly_more_output = 1;
	    }
	}
	len = iov[0].iov_len - d->s.avail_in;
	driver_deq(d->port, len);
    }

    if (d->want_crc) {
       d->crc = crc32(d->crc, (unsigned char*) d->bin->orig_bytes,
		      d->binsz - d->s.avail_out);
    }
    zlib_output(d);
    if (res == Z_STREAM_END) {       
       d->inflate_eos_seen = 1;
    }
    return res;
}
예제 #2
0
파일: zlib_drv.c 프로젝트: Airon2014/otp
static int zlib_deflate(ZLibData* d, int flush)
{
    int res = Z_OK;

    if ((d->bin == NULL) && (zlib_output_init(d) < 0)) {
	errno = ENOMEM;
	return Z_ERRNO;
    }

    while ((driver_sizeq(d->port) > 0) && (res != Z_STREAM_END)) {
	int vlen;
	SysIOVec* iov = driver_peekq(d->port, &vlen);
	int len;

	d->s.next_in = iov[0].iov_base;
	d->s.avail_in = iov[0].iov_len;

	while((d->s.avail_in > 0) && (res != Z_STREAM_END)) {
	    if ((res = deflate(&d->s, Z_NO_FLUSH)) < 0) {
		return res;
	    }
	    if (d->s.avail_out == 0) {
		zlib_output(d);
	    }
	}
	len = iov[0].iov_len - d->s.avail_in;
	if (d->want_crc) {
	    d->crc = crc32(d->crc, iov[0].iov_base, len);
	}
	driver_deq(d->port, len);
    }

    if (flush != Z_NO_FLUSH) {
	if ((res = deflate(&d->s, flush)) < 0) {
	    return res;
	}
	if (flush == Z_FINISH) {
	    while (d->s.avail_out < d->binsz) {
		zlib_output(d);
		if (res == Z_STREAM_END) {
		    break;
		}
		if ((res = deflate(&d->s, flush)) < 0) {
		    return res;
		}
	    }
	} else {
	    while (d->s.avail_out == 0) {
	       zlib_output(d);
	       if ((res = deflate(&d->s, flush)) < 0) {
		  return res;
	       }
	    }
	    if (d->s.avail_out < d->binsz) {
	       zlib_output(d);
	    }
	}
    }
    return res;
}
예제 #3
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);
    
  }
}
예제 #4
0
파일: echo_drv.c 프로젝트: aesedepece/otp
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;
    }
}
예제 #5
0
파일: zlib_drv.c 프로젝트: Airon2014/otp
static ErlDrvSSizeT zlib_ctl(ErlDrvData drv_data, unsigned int command, char *buf,
			     ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen)
{
    ZLibData* d = (ZLibData*)drv_data;
    int res;

    switch(command) {
    case DEFLATE_INIT:
	if (len != 4) goto badarg;
	if (d->state != ST_NONE) goto badarg;
	res = deflateInit(&d->s, i32(buf));
	if (res == Z_OK) {
	    d->state = ST_DEFLATE;
	    d->want_crc = 0;
	    d->crc = crc32(0L, Z_NULL, 0);
	}
	return zlib_return(res, rbuf, rlen);

    case DEFLATE_INIT2: {
	int wbits;

	if (len != 20) goto badarg;
	if (d->state != ST_NONE) goto badarg;
	wbits = i32(buf+8);
	res = deflateInit2(&d->s, i32(buf), i32(buf+4), wbits, 
			   i32(buf+12), i32(buf+16));
	if (res == Z_OK) {
	    d->state = ST_DEFLATE;
	    d->want_crc = (wbits < 0);
	    d->crc = crc32(0L, Z_NULL, 0);
	}
	return zlib_return(res, rbuf, rlen);
    }
	
    case DEFLATE_SETDICT:
	if (d->state != ST_DEFLATE) goto badarg;
	res = deflateSetDictionary(&d->s, (unsigned char*)buf, len);
	if (res == Z_OK) {
	    return zlib_value(d->s.adler, rbuf, rlen);
	} else {
	    return zlib_return(res, rbuf, rlen);
	}

    case DEFLATE_RESET:
	if (len != 0) goto badarg;
	if (d->state != ST_DEFLATE) goto badarg;
	driver_deq(d->port, driver_sizeq(d->port));
	res = deflateReset(&d->s);
	return zlib_return(res, rbuf, rlen);	
	
    case DEFLATE_END:
	if (len != 0) goto badarg;
	if (d->state != ST_DEFLATE) goto badarg;
	driver_deq(d->port, driver_sizeq(d->port));
	res = deflateEnd(&d->s);
	d->state = ST_NONE;
	return zlib_return(res, rbuf, rlen);

    case DEFLATE_PARAMS:
	if (len != 8) goto badarg;
	if (d->state != ST_DEFLATE) goto badarg;
	res = deflateParams(&d->s, i32(buf), i32(buf+4));
	return zlib_return(res, rbuf, rlen);

    case DEFLATE:
	if (d->state != ST_DEFLATE) goto badarg;
	if (len != 4) goto badarg;
	res = zlib_deflate(d, i32(buf));
	return zlib_return(res, rbuf, rlen);

    case INFLATE_INIT:
	if (len != 0) goto badarg;
	if (d->state != ST_NONE) goto badarg;
	res = inflateInit(&d->s);
	if (res == Z_OK) {
	    d->state = ST_INFLATE;
	    d->inflate_eos_seen = 0;
	    d->want_crc = 0;
	    d->crc = crc32(0L, Z_NULL, 0);
	}
	return zlib_return(res, rbuf, rlen);	
	
    case INFLATE_INIT2: {
	int wbits;

	if (len != 4) goto badarg;	
	if (d->state != ST_NONE) goto badarg;
	wbits = i32(buf);
	res = inflateInit2(&d->s, wbits);
	if (res == Z_OK) {
	    d->state = ST_INFLATE;
	    d->inflate_eos_seen = 0;
	    d->want_crc = (wbits < 0);
	    d->crc = crc32(0L, Z_NULL, 0);
	}
	return zlib_return(res, rbuf, rlen);
    }
	
    case INFLATE_SETDICT:
	if (d->state != ST_INFLATE) goto badarg;
	res = inflateSetDictionary(&d->s, (unsigned char*)buf, len);
	return zlib_return(res, rbuf, rlen);

    case INFLATE_SYNC:
	if (d->state != ST_INFLATE) goto badarg;
	if (len != 0) goto badarg;
	if (driver_sizeq(d->port) == 0) {
	    res = Z_BUF_ERROR;
	} else {
	    int vlen;
	    SysIOVec* iov = driver_peekq(d->port, &vlen);

	    d->s.next_in = iov[0].iov_base;
	    d->s.avail_in = iov[0].iov_len;
	    res = inflateSync(&d->s);
	}
	return zlib_return(res, rbuf, rlen);

    case INFLATE_RESET:
	if (d->state != ST_INFLATE) goto badarg;
	if (len != 0) goto badarg;
	driver_deq(d->port, driver_sizeq(d->port));
	res = inflateReset(&d->s);
	d->inflate_eos_seen = 0;
	return zlib_return(res, rbuf, rlen);

    case INFLATE_END:
	if (d->state != ST_INFLATE) goto badarg;
	if (len != 0) goto badarg;
	driver_deq(d->port, driver_sizeq(d->port));
	res = inflateEnd(&d->s);
	if (res == Z_OK && d->inflate_eos_seen == 0) {
	    res = Z_DATA_ERROR;
	}
	d->state = ST_NONE;
	return zlib_return(res, rbuf, rlen);

    case INFLATE:
	if (d->state != ST_INFLATE) goto badarg;
	if (len != 4) goto badarg;
	res = zlib_inflate(d, i32(buf));
	if (res == Z_NEED_DICT) {
	    return zlib_value2(3, d->s.adler, rbuf, rlen);
	} else {
	    return zlib_return(res, rbuf, rlen);
	}

    case GET_QSIZE:
	return zlib_value(driver_sizeq(d->port), rbuf, rlen);

    case GET_BUFSZ:
	return zlib_value(d->binsz_need, rbuf, rlen);

    case SET_BUFSZ: {
	int need;
	if (len != 4) goto badarg;
	need = i32(buf);
	if ((need < 16) || (need > 0x00ffffff))
	    goto badarg;
	if (d->binsz_need != need) {
	    d->binsz_need = need;
	    if (d->bin != NULL) {
		if (d->s.avail_out == d->binsz) {
		    driver_free_binary(d->bin);
		    d->bin = NULL;
		    d->binsz = 0;
		}
		else
		    zlib_output(d);
	    }
	}
	return zlib_return(Z_OK, rbuf, rlen);
    }

    case CRC32_0:
	return zlib_value(d->crc, rbuf, rlen);

    case CRC32_1: {
	uLong crc = crc32(0L, Z_NULL, 0);
	crc = crc32(crc, (unsigned char*) buf, len);
	return zlib_value(crc, rbuf, rlen);
    }
	
    case CRC32_2: {
	uLong crc;
	if (len < 4) goto badarg;
	crc = (unsigned int) i32(buf);
	crc = crc32(crc, (unsigned char*) buf+4, len-4);
	return zlib_value(crc, rbuf, rlen);
    }

    case ADLER32_1: {
	uLong adler = adler32(0L, Z_NULL, 0);
	adler = adler32(adler, (unsigned char*) buf, len);
	return zlib_value(adler, rbuf, rlen);
    }
	
    case ADLER32_2: {
       uLong adler;
       if (len < 4) goto badarg;
       adler = (unsigned int) i32(buf);
       adler = adler32(adler, (unsigned char*) buf+4, len-4);
       return zlib_value(adler, rbuf, rlen);
    }

    case CRC32_COMBINE: {
       uLong crc, crc1, crc2, len2;
       if (len != 12) goto badarg;
       crc1 = (unsigned int) i32(buf);
       crc2 = (unsigned int) i32(buf+4);
       len2 = (unsigned int) i32(buf+8);
       crc = crc32_combine(crc1, crc2, len2);
       return zlib_value(crc, rbuf, rlen);
    }

    case ADLER32_COMBINE: {
       uLong adler, adler1, adler2, len2;
       if (len != 12) goto badarg;
       adler1 = (unsigned int) i32(buf);
       adler2 = (unsigned int) i32(buf+4);
       len2   = (unsigned int) i32(buf+8);
       adler  = adler32_combine(adler1, adler2, len2);
       return zlib_value(adler, rbuf, rlen);
    }       
    }

 badarg:
    errno = EINVAL;
    return zlib_return(Z_ERRNO, rbuf, rlen);
}
예제 #6
0
파일: zlib_drv.c 프로젝트: Airon2014/otp
static void zlib_flush(ErlDrvData drv_data)
{
    ZLibData* d = (ZLibData*) drv_data;

    driver_deq(d->port, driver_sizeq(d->port));
}