static int
send_handshake (evutil_socket_t data_fd, BlockTxInfo *info)
{
    HandshakeRequest *req;

    if (sendn (data_fd, BLOCK_PROTOCOL_SIGNATURE, 37) < 0) {
        seaf_warning ("Failed to send protocol signature: %s.\n",
                      evutil_socket_error_to_string(evutil_socket_geterror(data_fd)));
        info->result = BLOCK_CLIENT_NET_ERROR;
        return -1;
    }

    int req_size = sizeof(HandshakeRequest) + info->enc_key_len;
    req = (HandshakeRequest *) g_malloc (req_size);
    req->version = htonl(BLOCK_PROTOCOL_VERSION);
    req->key_len = htonl(info->enc_key_len);
    memcpy (req->enc_session_key, info->enc_session_key, info->enc_key_len);

    if (sendn (data_fd, req, req_size) < 0) {
        seaf_warning ("Failed to send handshake: %s.\n",
                      evutil_socket_error_to_string(evutil_socket_geterror(data_fd)));
        info->result = BLOCK_CLIENT_NET_ERROR;
        g_free (req);
        return -1;
    }

    g_free (req);

    return 0;
}
Exemple #2
0
/**
 *  ################################################
 *
 *  Fun:
 *
 *  Author:
 *
 *  Date: Tue Dec  9 14:52:54 CST 2014
 *
 *  Purpose:
 *
 *
 *  Params:
 *
 *  Return:
 *
 *  ###################################################
 */
void event_cb(struct bufferevent *bev,short events, void *ctx)
{
	vLogErr(" the most recent error [%d] [%s]", EVUTIL_SOCKET_ERROR(),
		evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()));
	vLogErr("fd error is [%d] and error string [%s]",
		evutil_socket_geterror(bufferevent_getfd(bev)),
		evutil_socket_error_to_string(evutil_socket_geterror(bufferevent_getfd(bev))));
	if(events & BEV_EVENT_CONNECTED)
	{
		vLogErr("connected!\n");
	}
	else
	{
		if(events & BEV_EVENT_READING )
		{
			vLogErr("error [%d] [%s]!",events,evutil_socket_error_to_string(events));
			vLogErr("reading  error!\n");
		}
		if(events & BEV_EVENT_WRITING)
		{
			vLogErr("error [%d] [%s]!",events,evutil_socket_error_to_string(events));
			vLogErr("writing  error!\n");
		}
		if((events & BEV_EVENT_READING) && (events & BEV_EVENT_TIMEOUT))
		{
			vLogErr("error [%d] [%s]!",events,evutil_socket_error_to_string(events));
			vLogErr("reading timeout error!\n");
		}
		if((events & BEV_EVENT_WRITING) && (events & BEV_EVENT_TIMEOUT))
		{
			vLogErr("error [%d] [%s]!",events,evutil_socket_error_to_string(events));
			vLogErr("writing timeout error!\n");
		}
		if(events & BEV_EVENT_EOF)
		{
			vLogErr("error [%d] [%s]!",events,evutil_socket_error_to_string(events));
			vLogErr("eof file!\n");
		}
		if(events & BEV_EVENT_ERROR)
		{
			vLogErr("error [%d] [%s]!",events,evutil_socket_error_to_string(events));
		}
		if((events & BEV_EVENT_ERROR) && (events & BEV_EVENT_TIMEOUT))
		{
			vLogErr("error [%d] [%s]!",events,evutil_socket_error_to_string(events));
			vLogErr("timeout error!\n");
		}
		bufferevent_free(bev);
	}
}
Exemple #3
0
static void bufferevent_readcb(int32_t fd, short event, void *arg)
{
	struct bufferevent_common *bufev = arg;
	struct evbuffer *input;
	int res = 0;
	int len = 0;
	short what = BEV_EVENT_READING;
	struct evbuffer_common *pInput = bufev->input;
	
	if (event == EV_TIMEOUT) {
		/* Note that we only check for event==EV_TIMEOUT. If
		 * event==EV_TIMEOUT|EV_READ, we can safely ignore the
		 * timeout, since a read has occurred */
		what |= BEV_EVENT_TIMEOUT;
		goto error;
	}

	len = read(fd, pInput->data, 16384-pInput->len);
	pInput->data.len += len;
	if(pInput->data.len >= 4) {
		bev->len = *((int32_t *)(pInput->data));
	}
	
	
	if (len == -1) {
		int err = evutil_socket_geterror(fd);
		if (EVUTIL_ERR_RW_RETRIABLE(err))
			goto reschedule;
		/* error case */
		what |= BEV_EVENT_ERROR;
	} else if (len == 0) {
		/* eof case */
		what |= BEV_EVENT_EOF;
	}
	goto done:
error:
	if (event & EV_READ) {
		event_del(&bufev->ev_read);
	}
	bufev->errorcb(bufev, what);
done:
}

int32_t BUFFER_add(BUFFER *buffer, void *data, uint32_t len)
{
    uint32_t end = buffer->index + buffer->len;
    if(!buffer || len+buffer->len > buffer->capacity)
        return -1;
    if(end+len > buffer->capacity)
    {
        memcpy(buffer->data+end, data, capacity-end);
        memcpy(buffer->data, data+(capacity-end), end+len-buffer->capacity);
    }
    else
    {
        memcpy(buffer->data+end, data, len);
    }
    buffer->len += len;
    return 0;
}
Exemple #4
0
static void
listener_read_cb(evutil_socket_t fd, short what, void *p)
{
	struct evconnlistener *lev = (struct evconnlistener *)p;
	int err;
	evconnlistener_cb cb;
	evconnlistener_errorcb errorcb;
	void *user_data;
	LOCK(lev);
	while (1) {
		struct sockaddr_storage ss;
		ev_socklen_t socklen = sizeof(ss);
		evutil_socket_t new_fd = evutil_accept4_(fd, (struct sockaddr*)&ss, &socklen, lev->accept4_flags);
		if (new_fd < 0)
			break;
		if (socklen == 0) {
			/* This can happen with some older linux kernels in
			 * response to nmap. */
			evutil_closesocket(new_fd);
			continue;
		}

		if (lev->cb == NULL) {
			evutil_closesocket(new_fd);
			UNLOCK(lev);
			return;
		}
		++lev->refcnt;
		cb = lev->cb;
		user_data = lev->user_data;
		UNLOCK(lev);
		cb(lev, new_fd, (struct sockaddr*)&ss, (int)socklen,
		    user_data);
		LOCK(lev);
		if (lev->refcnt == 1) {
			int freed = listener_decref_and_unlock(lev);
			EVUTIL_ASSERT(freed);
			return;
		}
		--lev->refcnt;
	}
	err = evutil_socket_geterror(fd);
	if (EVUTIL_ERR_ACCEPT_RETRIABLE(err)) {
		UNLOCK(lev);
		return;
	}
	if (lev->errorcb != NULL) {
		++lev->refcnt;
		errorcb = lev->errorcb;
		user_data = lev->user_data;
		UNLOCK(lev);
		errorcb(lev, user_data);
		LOCK(lev);
		listener_decref_and_unlock(lev);
	} else {
		event_sock_warn(fd, "Error from accept() call");
	}
}
Exemple #5
0
static void
listener_read_cb(evutil_socket_t fd, short what, void *p)
{
	struct evconnlistener *lev = p;
	int err;
	evconnlistener_cb cb;
	evconnlistener_errorcb errorcb;
	void *user_data;
	LOCK(lev);
	while (1) {
		struct sockaddr_storage ss;
#ifdef WIN32
		int socklen = sizeof(ss);
#else
		socklen_t socklen = sizeof(ss);
#endif
		evutil_socket_t new_fd = accept(fd, (struct sockaddr*)&ss, &socklen);
		if (new_fd < 0)
			break;

		if (!(lev->flags & LEV_OPT_LEAVE_SOCKETS_BLOCKING))
			evutil_make_socket_nonblocking(new_fd);

		if (lev->cb == NULL) {
			UNLOCK(lev);
			return;
		}
		++lev->refcnt;
		cb = lev->cb;
		user_data = lev->user_data;
		UNLOCK(lev);
		cb(lev, new_fd, (struct sockaddr*)&ss, (int)socklen,
		    user_data);
		LOCK(lev);
		if (lev->refcnt == 1) {
			int freed = listener_decref_and_unlock(lev);
			EVUTIL_ASSERT(freed);
			return;
		}
		--lev->refcnt;
	}
	err = evutil_socket_geterror(fd);
	if (EVUTIL_ERR_ACCEPT_RETRIABLE(err)) {
		UNLOCK(lev);
		return;
	}
	if (lev->errorcb != NULL) {
		++lev->refcnt;
		errorcb = lev->errorcb;
		user_data = lev->user_data;
		UNLOCK(lev);
		errorcb(lev, user_data);
		LOCK(lev);
		listener_decref_and_unlock(lev);
	} else {
		event_sock_warn(fd, "Error from accept() call");
	}
}
static evutil_socket_t
connect_chunk_server (ChunkServer *cs)
{
    struct sockaddr_in sa;
    ev_socklen_t sa_len;
    evutil_socket_t data_fd;
    ev_socklen_t optlen;

    if (dns_lookup (cs->addr, &sa, &sa_len) < 0) {
        return -1;
    }

    sa.sin_family = AF_INET;
    sa.sin_port = htons(cs->port);

    data_fd = socket (AF_INET, SOCK_STREAM, 0);
    if (data_fd < 0) {
        seaf_warning ("socket error: %s.\n", strerror(errno));
        return -1;
    }

#ifdef WIN32
    /* Set large enough TCP buffer size.
     * This greatly enhances sync speed for high latency network.
     * Windows by default use 8KB buffers, which is too small for such case.
     * Linux has auto-tuning for TCP buffers, so don't need to set manually.
     * OSX is TBD.
     */

#define DEFAULT_SNDBUF_SIZE (1 << 16) /* 64KB */

    /* Set send buffer size. */
    int sndbuf_size;
    optlen = sizeof(int);
    getsockopt (data_fd, SOL_SOCKET, SO_SNDBUF, (char *)&sndbuf_size, &optlen);

    if (sndbuf_size < DEFAULT_SNDBUF_SIZE) {
        sndbuf_size = DEFAULT_SNDBUF_SIZE;
        optlen = sizeof(int);
        setsockopt (data_fd, SOL_SOCKET, SO_SNDBUF, (char *)&sndbuf_size, optlen);
    }
#endif

    /* Disable Nagle's algorithm. */
    int val = 1;
    optlen = sizeof(int);
    setsockopt (data_fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, optlen);

    if (connect (data_fd, (struct sockaddr *)&sa, sa_len) < 0) {
        seaf_warning ("connect error: %s.\n",
                      evutil_socket_error_to_string(evutil_socket_geterror(data_fd)));
        evutil_closesocket (data_fd);
        return -1;
    }

    return data_fd;
}
Exemple #7
0
void
event_sock_warn(evutil_socket_t sock, const char *fmt, ...)
{
	va_list ap;
	int err = evutil_socket_geterror(sock);

	va_start(ap, fmt);
	_warn_helper(_EVENT_LOG_WARN, evutil_socket_error_to_string(err), fmt, ap);
	va_end(ap);
}
Exemple #8
0
void
event_sock_err(int eval, evutil_socket_t sock, const char *fmt, ...)
{
	va_list ap;
	int err = evutil_socket_geterror(sock);

	va_start(ap, fmt);
	warn_helper_(EVENT_LOG_ERR, evutil_socket_error_to_string(err), fmt, ap);
	va_end(ap);
	event_exit(eval);
}
Exemple #9
0
void
do_read(evutil_socket_t fd, short events, void *arg)
{
    struct fd_state *state = arg;
    char buf[1024];
    int i;
    ev_ssize_t result;

    printf("do_read(): fd = %d\r\n", fd);
    while (1) {
        assert(state->write_event);
        result = recv(fd, buf, sizeof(buf), 0);
        printf("recv(): result = %d\r\n", result);
        if (result <= 0)
            break;

        for (i=0; i < result; ++i)  {
            if (state->buffer_used < sizeof(state->buffer))
                state->buffer[state->buffer_used++] = rot13_char(buf[i]);
            if (buf[i] == '\n') {
                //assert(state->write_event);
                //event_add(state->write_event, NULL);
                state->write_upto = state->buffer_used;
                buf[state->buffer_used] = '\0';
                printf("\r\n");
                printf("bufsize = %d, buf = %s\r\n", state->buffer_used, buf);
            }
        }
    }

    if (result == 0) {
        free_fd_state(state);
    } else if (result < 0) {
        //if (errno == EAGAIN) // XXXX use evutil macro
        //    return;
        int err = evutil_socket_geterror(fd);
        if (EVUTIL_ERR_RW_RETRIABLE(err)) {
            // WSAEWOULDBLOCK or WSAEINTR
            printf("event_del(state->read_event);\r\n");
            event_del(state->read_event);
            return;
        }
        else {
            perror("recv");
            free_fd_state(state);
        }
    }
}
Exemple #10
0
static int
send_handshake_response (BlockTxServer *server, int status)
{
    HandshakeResponse rsp;

    rsp.status = htonl (status);
    rsp.version = htonl (BLOCK_PROTOCOL_VERSION);

    if (sendn (server->data_fd, &rsp, sizeof(rsp)) < 0) {
        seaf_warning ("Failed to send handshake response: %s.\n",
                      evutil_socket_error_to_string(evutil_socket_geterror(server->data_fd)));
        return -1;
    }

    return 0;
}
Exemple #11
0
void CBareConnection::conn_event(bufferevent* bev, short event, void* ctx)
{
    assert(bev != nullptr);
    assert(ctx != nullptr);
    CBareConnection* data = static_cast<CBareConnection*>(ctx);
    if ((event & BEV_EVENT_CONNECTED) != 0)
        data->OnConnectSuccess(std::move(data->m_bev));
    else {
        evutil_socket_t sock = bufferevent_getfd(bev);
        (void)sock;
        // sock may be BAD_SOCKET here if it wasn't successfully created.
        int error = evutil_socket_geterror(sock);
        data->m_bev.free();
        data->OnConnectFailure(event, error);
    }
}
Exemple #12
0
void
do_write(evutil_socket_t fd, short events, void *arg)
{
    struct fd_state *state = arg;
    char buf[512];
    int n_written = 0, write_upto = sizeof(buf);
    int buffer_used = 0;

    printf("do_write(): fd = %d\r\n", fd);

    memset(buf, 0, write_upto);
    strcpy(buf, "Hello World!\r\n");

    printf("\r\n");
    printf("bufsize = %d, buf = %s\r\n", state->buffer_used, buf);

    write_upto = strlen(buf);

    while (n_written < write_upto) {
        ev_ssize_t result = send(fd, buf + n_written,
                              write_upto - n_written, 0);
        printf("send(): result = %d\r\n", result);
        if (result < 0) {
            //if (errno == EAGAIN) // XXX use evutil macro
            //    return;
		    int err = evutil_socket_geterror(fd);
            if (EVUTIL_ERR_RW_RETRIABLE(err)) {
                // WSAEWOULDBLOCK or WSAEINTR
                break;
            }
            else {
                printf("event_del(state->write_event);\r\n");
                event_del(state->write_event);
                return;
            }
        }
        assert(result != 0);

        n_written += result;
    }

    if (n_written == buffer_used)
        n_written = write_upto = buffer_used = 1;

    printf("event_del(state->write_event);\r\n");
    event_del(state->write_event);
}
static int
launch_request(void)
{
	evutil_socket_t sock;
	struct sockaddr_in sin;
	struct bufferevent *b;

	struct request_info *ri;

	memset(&sin, 0, sizeof(sin));

	++total_n_launched;

	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = htonl(0x7f000001);
	sin.sin_port = htons(8080);
	if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
		return -1;
	if (evutil_make_socket_nonblocking(sock) < 0) {
		evutil_closesocket(sock);
		return -1;
	}
	frob_socket(sock);
	if (connect(sock, (struct sockaddr*)&sin, sizeof(sin)) < 0) {
		int e = evutil_socket_geterror(sock);
		if (! EVUTIL_ERR_CONNECT_RETRIABLE(e)) {
			evutil_closesocket(sock);
			return -1;
		}
	}

	ri = malloc(sizeof(*ri));
	ri->n_read = 0;
	evutil_gettimeofday(&ri->started, NULL);

	b = bufferevent_socket_new(base, sock, BEV_OPT_CLOSE_ON_FREE);

	bufferevent_setcb(b, readcb, NULL, errorcb, ri);
	bufferevent_enable(b, EV_READ|EV_WRITE);

	evbuffer_add_printf(bufferevent_get_output(b),
	    "GET %s HTTP/1.0\r\n\r\n", resource);

	return 0;
}
static void
recv_data_cb (BlockTxClient *client)
{
    int ret = 0;

    /* Let evbuffer determine how much data can be read. */
    int n = evbuffer_read (client->recv_buf, client->data_fd, -1);
    if (n == 0) {
        seaf_warning ("Data connection is closed by the server.\n");
        client->break_loop = TRUE;
        client->info->result = BLOCK_CLIENT_NET_ERROR;
        return;
    } else if (n < 0) {
        seaf_warning ("Read data connection error: %s.\n",
                      evutil_socket_error_to_string(evutil_socket_geterror(client->data_fd)));
        client->break_loop = TRUE;
        client->info->result = BLOCK_CLIENT_NET_ERROR;
        return;
    }

    switch (client->recv_state) {
    case RECV_STATE_HANDSHAKE:
        ret = handle_handshake_response (client);
        break;
    case RECV_STATE_AUTH:
        ret = handle_auth_response (client);
        break;
    case RECV_STATE_HEADER:
        ret = handle_block_header (client);
        if (ret < 0)
            break;

        if (client->recv_state == RECV_STATE_CONTENT &&
            client->info->task->type == TASK_TYPE_DOWNLOAD)
            ret = handle_block_content (client);

        break;
    case RECV_STATE_CONTENT:
        ret = handle_block_content (client);
        break;
    }

    if (ret < 0)
        client->break_loop = TRUE;
}
Exemple #15
0
ssize_t ec_net_pullup(evutil_socket_t sd, uint8_t *b, size_t b_sz,
        int *flags, struct sockaddr *peer, socklen_t *peer_len, int *e)
{
    ssize_t n;
    struct msghdr msg;
    struct iovec iov[1];

    dbg_return_if (sd == -1, -1);
    dbg_return_if (b == NULL, -1);
    dbg_return_if (e == NULL, -1);
    dbg_return_if (flags == NULL, -1);
    /* b_sz==0 allowed here ? */

    memset(&msg, sizeof msg, 0);

    msg.msg_name = peer;
    msg.msg_namelen = *peer_len;
    iov[0].iov_base = b;
    iov[0].iov_len = b_sz;
    msg.msg_control = NULL;
    msg.msg_controllen = 0;
    msg.msg_iov = iov;
    msg.msg_iovlen = 1;

    *e = 0;

    if ((n = recvmsg(sd, &msg, *flags)) < 0)
    {
        if ((*e = evutil_socket_geterror(sd)) != EAGAIN)
            u_dbg("%s", evutil_socket_error_to_string(*e));
     
        goto err;
    }

    *flags = msg.msg_flags;

    /* TODO retrieve cmsg with type IP_RECVDSTADDR to tell datagrams that 
       where sent to a multicast destination. */

    return n;
err:
    return -1;
}
Exemple #16
0
static void
recv_data_cb (BlockTxServer *server)
{
    int ret = 0;

    /* Let evbuffer determine how much data can be read. */
    int n = evbuffer_read (server->recv_buf, server->data_fd, -1);
    if (n == 0) {
        seaf_debug ("Data connection is closed by the client. Transfer done.\n");
        server->break_loop = TRUE;
        return;
    } else if (n < 0) {
        seaf_warning ("Read data connection error: %s.\n",
                      evutil_socket_error_to_string(evutil_socket_geterror(server->data_fd)));
        server->break_loop = TRUE;
        return;
    }

    switch (server->recv_state) {
    case RECV_STATE_HANDSHAKE:
        ret = handle_handshake_request (server);
        break;
    case RECV_STATE_AUTH:
        ret = handle_auth_request (server);
        break;
    case RECV_STATE_HEADER:
        ret = handle_block_header (server);
        if (ret < 0)
            break;

        if (server->recv_state == RECV_STATE_CONTENT &&
            server->command == REQUEST_COMMAND_PUT)
            ret = handle_block_content (server);

        break;
    case RECV_STATE_CONTENT:
        ret = handle_block_content (server);
        break;
    }

    if (ret < 0)
        server->break_loop = TRUE;
}
Exemple #17
0
/* Callback for when the signal handler write a byte to our signaling socket */
static void
evsig_cb(evutil_socket_t fd, short what, void *arg)
{
	static char signals[1024];
	ev_ssize_t n;
	int i;
	int ncaught[NSIG];
	struct event_base *base;

	base = arg;

	memset(&ncaught, 0, sizeof(ncaught));

	while (1) {
#ifdef _WIN32
		n = recv(fd, signals, sizeof(signals), 0);
#else
		n = read(fd, signals, sizeof(signals));
#endif
		if (n == -1) {
			int err = evutil_socket_geterror(fd);
			if (! EVUTIL_ERR_RW_RETRIABLE(err))
				event_sock_err(1, fd, "%s: recv", __func__);
			break;
		} else if (n == 0) {
			/* XXX warn? */
			break;
		}
		for (i = 0; i < n; ++i) {
			ev_uint8_t sig = signals[i];
			if (sig < NSIG)
				ncaught[sig]++;
		}
	}

	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
	for (i = 0; i < NSIG; ++i) {
		if (ncaught[i])
			evmap_signal_active_(base, i, ncaught[i]);
	}
	EVBASE_RELEASE_LOCK(base, th_base_lock);
}
Exemple #18
0
void Listener::read_cb(evutil_socket_t fd, short what){
  
  //TODO:locker
  //LOCK(lev);
  while (true) {
    struct sockaddr_storage ss;
#ifdef WIN32
    int socklen = sizeof(ss);
#else
    socklen_t socklen = sizeof(ss);
#endif
    evutil_socket_t new_fd = accept(fd, (struct sockaddr*)&ss, &socklen);
    if (!isSocketValid(new_fd)) break;

    if (!(this->flags & LEV_OPT_LEAVE_SOCKETS_BLOCKING))
      evutil_make_socket_nonblocking(new_fd);


    ++this->refcnt;
    //TODO
    //UNLOCK(lev);
    this->on_new_conn_accepted(new_fd,(struct sockaddr*)&ss, (int)socklen);    
    //LOCK(lev);
    if (this->refcnt == 1) {
      MYASSERT(this->decref_and_unlock());      
      return;
    } else --this->refcnt;
  }
  int err = evutil_socket_geterror(fd);
  if (!MY_ERR_ACCEPT_RETRIABLE(err)) {
    ++this->refcnt;
    //UNLOCK(lev);
    this->on_fatal_error();
    //LOCK(lev);
    this->decref_and_unlock();
  } 
  //TODO
  //UNLOCK(lev);  
}
Exemple #19
0
/* Callback for when the signal handler write a byte to our signaling socket */
static void
evsig_cb(evutil_socket_t fd, short what, void *arg)
{
	static char signals[1024];//用来存放信号处理函数传过来的的信号?
	ev_ssize_t n;
	int i;
	int ncaught[NSIG];//NSIG在哪定义?
	struct event_base *base;

	base = arg;

	memset(&ncaught, 0, sizeof(ncaught));

	while (1) {
		n = recv(fd, signals, sizeof(signals), 0);
		if (n == -1) {
			int err = evutil_socket_geterror(fd);//windows平台这是函数,而linux平台这是宏函数
			if (! EVUTIL_ERR_RW_RETRIABLE(err)) //判断是否可重读写,即检查EINTR和EAGAIN
				event_sock_err(1, fd, "%s: recv", __func__);
			break;
		} else if (n == 0) {
			/* XXX warn? */
			break;
		}
		for (i = 0; i < n; ++i) {
			ev_uint8_t sig = signals[i];
			if (sig < NSIG)
				ncaught[sig]++;//记录传进来的信号
		}
	}

	EVBASE_ACQUIRE_LOCK(base, th_base_lock);//base虽然是在本函数中定义的,貌似在栈上,但是他指向的地址是从外部传过来的,所以需要加锁
	for (i = 0; i < NSIG; ++i) {
		if (ncaught[i])
			evmap_signal_active(base, i, ncaught[i]);//激活base中等待的信号
	}
	EVBASE_RELEASE_LOCK(base, th_base_lock);
}
Exemple #20
0
static void
listener_read_cb(evutil_socket_t fd, short what, void *p)
{
	struct evconnlistener *lev = p;
	int err;
	while (1) {
		struct sockaddr_storage ss;
		socklen_t socklen = sizeof(ss);

		evutil_socket_t new_fd = accept(fd, (struct sockaddr*)&ss, &socklen);
		if (new_fd < 0)
			break;

		if (!(lev->flags & LEV_OPT_LEAVE_SOCKETS_BLOCKING))
			evutil_make_socket_nonblocking(new_fd);

		lev->cb(lev, new_fd, (struct sockaddr*)&ss, (int)socklen,
		    lev->user_data);
	}
	err = evutil_socket_geterror(fd);
	if (EVUTIL_ERR_ACCEPT_RETRIABLE(err))
		return;
	event_sock_warn(fd, "Error from accept() call");
}
Exemple #21
0
static void
bufferevent_writecb(evutil_socket_t fd, short event, void *arg)
{
	struct bufferevent *bufev = arg;
	struct bufferevent_private *bufev_p =
	    EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
	int res = 0;
	short what = BEV_EVENT_WRITING;
	int connected = 0;
	ev_ssize_t atmost = -1;

	_bufferevent_incref_and_lock(bufev);

	if (event == EV_TIMEOUT) {
		/* Note that we only check for event==EV_TIMEOUT. If
		 * event==EV_TIMEOUT|EV_WRITE, we can safely ignore the
		 * timeout, since a read has occurred */
		what |= BEV_EVENT_TIMEOUT;
		goto error;
	}
	//正在连接服务器...
	if (bufev_p->connecting) {
		int c = evutil_socket_finished_connecting(fd);
		/* we need to fake the error if the connection was refused
		 * immediately - usually connection to localhost on BSD */
		if (bufev_p->connection_refused) {  //在bufferevent_socket_connect中被设置
		  bufev_p->connection_refused = 0;
		  c = -1;
		}

		if (c == 0) //正在连接,继续监听可写。
			goto done;

		bufev_p->connecting = 0;
		if (c < 0) {  //连接发生错误
			event_del(&bufev->ev_write);
			event_del(&bufev->ev_read);
			_bufferevent_run_eventcb(bufev, BEV_EVENT_ERROR);
			goto done;
		} else {  //连接成功
			connected = 1;
#ifdef WIN32
			if (BEV_IS_ASYNC(bufev)) {
				event_del(&bufev->ev_write);
				bufferevent_async_set_connected(bufev);
				_bufferevent_run_eventcb(bufev,
						BEV_EVENT_CONNECTED);
				goto done;
			}
#endif
            //连接成功,调用用户错误处理函数。比较奇怪。
			_bufferevent_run_eventcb(bufev,
					BEV_EVENT_CONNECTED);
			if (!(bufev->enabled & EV_WRITE) ||
			    bufev_p->write_suspended) {
				event_del(&bufev->ev_write);
				goto done;
			}
		}
	}

	atmost = _bufferevent_get_write_max(bufev_p);

    //写被挂起
	if (bufev_p->write_suspended)
		goto done;

    //存在可写数据
	if (evbuffer_get_length(bufev->output)) {
		evbuffer_unfreeze(bufev->output, 1);
		//将缓冲区数据写入socket。
		res = evbuffer_write_atmost(bufev->output, fd, atmost);
		evbuffer_freeze(bufev->output, 1);
		if (res == -1) {  //写发生错误
			int err = evutil_socket_geterror(fd);
			if (EVUTIL_ERR_RW_RETRIABLE(err))  //socket缓冲区满,一次未写完,继续监听可写事件,等待下次写入。
				goto reschedule;
			what |= BEV_EVENT_ERROR;  //写发生异常错误
		} else if (res == 0) {
			/* eof case
			   XXXX Actually, a 0 on write doesn't indicate
			   an EOF. An ECONNRESET might be more typical.
			 */
			what |= BEV_EVENT_EOF;
		}
		if (res <= 0)
			goto error;

		_bufferevent_decrement_write_buckets(bufev_p, res);
	}

    //缓冲区数据已写完,删除写事件。
	if (evbuffer_get_length(bufev->output) == 0) {
		event_del(&bufev->ev_write);
	}

	/* 低于写低水位,调用用户回调。
	 */
	if ((res || !connected) &&
	    evbuffer_get_length(bufev->output) <= bufev->wm_write.low) {
		_bufferevent_run_writecb(bufev);
	}

	goto done;

 reschedule:
	if (evbuffer_get_length(bufev->output) == 0) {
		event_del(&bufev->ev_write);
	}
	goto done;

 error:
	bufferevent_disable(bufev, EV_WRITE);
	_bufferevent_run_eventcb(bufev, what);

 done:
	_bufferevent_decref_and_unlock(bufev);
}
Exemple #22
0
static void
bufferevent_readcb(evutil_socket_t fd, short event, void *arg)
{
	struct bufferevent *bufev = arg;
	struct bufferevent_private *bufev_p =
	    EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
	struct evbuffer *input;
	int res = 0;
	short what = BEV_EVENT_READING;
	ev_ssize_t howmuch = -1, readmax=-1;

	_bufferevent_incref_and_lock(bufev);

	if (event == EV_TIMEOUT) {
		/* Note that we only check for event==EV_TIMEOUT. If
		 * event==EV_TIMEOUT|EV_READ, we can safely ignore the
		 * timeout, since a read has occurred */
		what |= BEV_EVENT_TIMEOUT;
		goto error;
	}

	input = bufev->input;

	/*
	 * If we have a high watermark configured then we don't want to
	 * read more data than would make us reach the watermark.
	 */
	if (bufev->wm_read.high != 0) {
		howmuch = bufev->wm_read.high - evbuffer_get_length(input);
		/* 缓冲区超过高水位,挂起读。 */
		if (howmuch <= 0) {
			bufferevent_wm_suspend_read(bufev);
			goto done;
		}
	}
	
	//因为用户可以限速,所以这么要检测最大的可读大小。  
    //如果没有限速的话,那么将返回16384字节,即16K  
    //默认情况下是没有限速的。  
	readmax = _bufferevent_get_read_max(bufev_p);
	if (howmuch < 0 || howmuch > readmax) /* The use of -1 for "unlimited"
					       * uglifies this code. XXXX */
		howmuch = readmax;
	if (bufev_p->read_suspended)
		goto done;

	evbuffer_unfreeze(input, 0);
	res = evbuffer_read(input, fd, (int)howmuch); /* XXXX evbuffer_read would do better to take and return ev_ssize_t */
	evbuffer_freeze(input, 0);

	if (res == -1) {
		int err = evutil_socket_geterror(fd);
		if (EVUTIL_ERR_RW_RETRIABLE(err))  //EINTER or EAGAIN 
			goto reschedule;
		/* error case */
		what |= BEV_EVENT_ERROR;
	} else if (res == 0) {
		/* eof case */
		what |= BEV_EVENT_EOF;
	}

	if (res <= 0)
		goto error;

	_bufferevent_decrement_read_buckets(bufev_p, res);

	/* 数据大于低水平,调用用户设置的回调。 */
	if (evbuffer_get_length(input) >= bufev->wm_read.low)
		_bufferevent_run_readcb(bufev);

	goto done;

 reschedule:
	goto done;

 error:
	bufferevent_disable(bufev, EV_READ);
	_bufferevent_run_eventcb(bufev, what);

 done:
	_bufferevent_decref_and_unlock(bufev);
}
Exemple #23
0
const char *
socket_error_string(evutil_socket_t s)
{
	return evutil_socket_error_to_string(evutil_socket_geterror(s));
}
Exemple #24
0
static void
bufferevent_readcb(evutil_socket_t fd, short event, void *arg)
{
	struct bufferevent *bufev = arg;
	struct bufferevent_private *bufev_p =
	    EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
	struct evbuffer *input;
	int res = 0;
	short what = BEV_EVENT_READING;
	ev_ssize_t howmuch = -1, readmax=-1;

	bufferevent_incref_and_lock_(bufev);

	if (event == EV_TIMEOUT) {
		/* Note that we only check for event==EV_TIMEOUT. If
		 * event==EV_TIMEOUT|EV_READ, we can safely ignore the
		 * timeout, since a read has occurred */
		what |= BEV_EVENT_TIMEOUT;
		goto error;
	}

	input = bufev->input;

	/*
	 * If we have a high watermark configured then we don't want to
	 * read more data than would make us reach the watermark.
	 */
	if (bufev->wm_read.high != 0) {
		howmuch = bufev->wm_read.high - evbuffer_get_length(input);
		/* we somehow lowered the watermark, stop reading */
		if (howmuch <= 0) {
			bufferevent_wm_suspend_read(bufev);
			goto done;
		}
	}
	readmax = bufferevent_get_read_max_(bufev_p);
	if (howmuch < 0 || howmuch > readmax) /* The use of -1 for "unlimited"
					       * uglifies this code. XXXX */
		howmuch = readmax;
	if (bufev_p->read_suspended)
		goto done;

	evbuffer_unfreeze(input, 0);
	res = evbuffer_read(input, fd, (int)howmuch); /* XXXX evbuffer_read would do better to take and return ev_ssize_t */
	evbuffer_freeze(input, 0);

	if (res == -1) {
		int err = evutil_socket_geterror(fd);
		if (EVUTIL_ERR_RW_RETRIABLE(err))
			goto reschedule;
		/* error case */
		what |= BEV_EVENT_ERROR;
	} else if (res == 0) {
		/* eof case */
		what |= BEV_EVENT_EOF;
	}

	if (res <= 0)
		goto error;

	bufferevent_decrement_read_buckets_(bufev_p, res);

	/* Invoke the user callback - must always be called last */
	if (evbuffer_get_length(input) >= bufev->wm_read.low)
		bufferevent_run_readcb_(bufev);

	goto done;

 reschedule:
	goto done;

 error:
	bufferevent_disable(bufev, EV_READ);
	bufferevent_run_eventcb_(bufev, what);

 done:
	bufferevent_decref_and_unlock_(bufev);
}
 static int64_t HHVM_STATIC_METHOD(EventUtil, getLastSocketErrno, const Resource &socket){
     if(socket.isNull()){
         return EVUTIL_SOCKET_ERROR();
     }
     return evutil_socket_geterror(resource_to_fd(socket.asCResRef()));
 }
Exemple #26
0
static void
bufferevent_writecb(evutil_socket_t fd, short event, void *arg)
{
	struct bufferevent *bufev = arg;
	struct bufferevent_private *bufev_p =
	    EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
	int res = 0;
	short what = BEV_EVENT_WRITING;
	int connected = 0;
	ev_ssize_t atmost = -1;

	bufferevent_incref_and_lock_(bufev);

	if (event == EV_TIMEOUT) {
		/* Note that we only check for event==EV_TIMEOUT. If
		 * event==EV_TIMEOUT|EV_WRITE, we can safely ignore the
		 * timeout, since a read has occurred */
		what |= BEV_EVENT_TIMEOUT;
		goto error;
	}
	if (bufev_p->connecting) {
		int c = evutil_socket_finished_connecting_(fd);
		/* we need to fake the error if the connection was refused
		 * immediately - usually connection to localhost on BSD */
		if (bufev_p->connection_refused) {
		  bufev_p->connection_refused = 0;
		  c = -1;
		}

		if (c == 0)
			goto done;

		bufev_p->connecting = 0;
		if (c < 0) {
			event_del(&bufev->ev_write);
			event_del(&bufev->ev_read);
			bufferevent_run_eventcb_(bufev, BEV_EVENT_ERROR);
			goto done;
		} else {
			connected = 1;
#ifdef _WIN32
			if (BEV_IS_ASYNC(bufev)) {
				event_del(&bufev->ev_write);
				bufferevent_async_set_connected_(bufev);
				bufferevent_run_eventcb_(bufev,
						BEV_EVENT_CONNECTED);
				goto done;
			}
#endif
			bufferevent_run_eventcb_(bufev,
					BEV_EVENT_CONNECTED);
			if (!(bufev->enabled & EV_WRITE) ||
			    bufev_p->write_suspended) {
				event_del(&bufev->ev_write);
				goto done;
			}
		}
	}

	atmost = bufferevent_get_write_max_(bufev_p);

	if (bufev_p->write_suspended)
		goto done;

	if (evbuffer_get_length(bufev->output)) {
		evbuffer_unfreeze(bufev->output, 1);
		res = evbuffer_write_atmost(bufev->output, fd, atmost);
		evbuffer_freeze(bufev->output, 1);
		if (res == -1) {
			int err = evutil_socket_geterror(fd);
			if (EVUTIL_ERR_RW_RETRIABLE(err))
				goto reschedule;
			what |= BEV_EVENT_ERROR;
		} else if (res == 0) {
			/* eof case
			   XXXX Actually, a 0 on write doesn't indicate
			   an EOF. An ECONNRESET might be more typical.
			 */
			what |= BEV_EVENT_EOF;
		}
		if (res <= 0)
			goto error;

		bufferevent_decrement_write_buckets_(bufev_p, res);
	}

	if (evbuffer_get_length(bufev->output) == 0) {
		event_del(&bufev->ev_write);
	}

	/*
	 * Invoke the user callback if our buffer is drained or below the
	 * low watermark.
	 */
	if ((res || !connected) &&
	    evbuffer_get_length(bufev->output) <= bufev->wm_write.low) {
		bufferevent_run_writecb_(bufev);
	}

	goto done;

 reschedule:
	if (evbuffer_get_length(bufev->output) == 0) {
		event_del(&bufev->ev_write);
	}
	goto done;

 error:
	bufferevent_disable(bufev, EV_WRITE);
	bufferevent_run_eventcb_(bufev, what);

 done:
	bufferevent_decref_and_unlock_(bufev);
}
 static String HHVM_STATIC_METHOD(EventUtil, getLastSocketError, const Resource &socket){
     if(socket.isNull()){
         return StringData::Make(evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()));
     }
     return StringData::Make(evutil_socket_geterror(resource_to_fd(socket.asCResRef())));
 }