Ejemplo n.º 1
0
struct bufferevent *
bufferevent_socket_new(struct event_base *base, evutil_socket_t fd,
    int options)
{
	struct bufferevent_private *bufev_p;
	struct bufferevent *bufev;

#ifdef _WIN32
	if (base && event_base_get_iocp_(base))
		return bufferevent_async_new_(base, fd, options);
#endif

	if ((bufev_p = mm_calloc(1, sizeof(struct bufferevent_private)))== NULL)
		return NULL;

	if (bufferevent_init_common_(bufev_p, base, &bufferevent_ops_socket,
				    options) < 0) {
		mm_free(bufev_p);
		return NULL;
	}
	bufev = &bufev_p->bev;
	evbuffer_set_flags(bufev->output, EVBUFFER_FLAG_DRAINS_TO_FD);

	event_assign(&bufev->ev_read, bufev->ev_base, fd,
	    EV_READ|EV_PERSIST, bufferevent_readcb, bufev);
	event_assign(&bufev->ev_write, bufev->ev_base, fd,
	    EV_WRITE|EV_PERSIST, bufferevent_writecb, bufev);

	evbuffer_add_cb(bufev->output, bufferevent_socket_outbuf_cb, bufev);

	evbuffer_freeze(bufev->input, 0);
	evbuffer_freeze(bufev->output, 1);

	return bufev;
}
Ejemplo n.º 2
0
struct bufferevent *
bufferevent_socket_new(struct event_base *base, evutil_socket_t fd,
    int options)
{
	struct bufferevent_private *bufev_p;
	struct bufferevent *bufev;

#ifdef WIN32
	if (base && event_base_get_iocp(base))
		return bufferevent_async_new(base, fd, options);
#endif

	if ((bufev_p = mm_calloc(1, sizeof(struct bufferevent_private)))== NULL)
		return NULL;

	if (bufferevent_init_common(bufev_p, base, &bufferevent_ops_socket,
				    options) < 0) {
		mm_free(bufev_p);
		return NULL;
	}
	bufev = &bufev_p->bev;
	//设置将evbuffer的数据向fd传 
	evbuffer_set_flags(bufev->output, EVBUFFER_FLAG_DRAINS_TO_FD);

    //设置读写回调
	event_assign(&bufev->ev_read, bufev->ev_base, fd,
	    EV_READ|EV_PERSIST, bufferevent_readcb, bufev);
	event_assign(&bufev->ev_write, bufev->ev_base, fd,
	    EV_WRITE|EV_PERSIST, bufferevent_writecb, bufev);

    //设置evbuffer的回调函数,使得外界给写缓冲区添加数据时,能触发  
    //写操作,这个回调对于写事件的监听是很重要的  
	evbuffer_add_cb(bufev->output, bufferevent_socket_outbuf_cb, bufev);

	/* 虽然这里冻结了,但实际上Libevent在读数据或者写数据之前会解冻的读完或者写完数据后,又会马上冻结。
	 * 这主要防止数据被意外修改。用户一般不会直接调用evbuffer_freeze或者evbuffer_unfreeze函数。
	 * 一切的冻结和解冻操作都由Libevent内部完成。还有一点要注意,因为这里只是把写缓冲区的头部冻结了。
	 * 所以还是可以往写缓冲区的尾部追加数据。同样,此时也是可以从读缓冲区读取数据。这个是必须的。
	 * 因为在Libevent内部不解冻的时候,用户需要从读缓冲区中获取数据(这相当于从socket fd中读取数据),
	 * 用户也需要把数据写到写缓冲区中(这相当于把数据写入到socket fd中)。*/

    //冻结读缓冲区的尾部,未解冻之前不能往读缓冲区追加数据  
    //也就是说不能从socket fd中读取数据  
	evbuffer_freeze(bufev->input, 0);

	//冻结写缓冲区的头部,未解冻之前不能把写缓冲区的头部数据删除  
    //也就是说不能把数据写到socket fd  
	evbuffer_freeze(bufev->output, 1);

	return bufev;
}
Ejemplo n.º 3
0
/**
 * Called by libevent when there is data to read.
 */
void buffered_on_read(struct bufferevent *bev, void *arg) {
	client_t *client = (client_t *)arg;
	char *line;
	size_t n;
	/* If we have input data, the number of bytes we have is contained in
	 * bev->input->off. Copy the data from the input buffer to the output
	 * buffer in 4096-byte chunks. There is a one-liner to do the whole thing
	 * in one shot, but the purpose of this server is to show actual real-world
	 * reading and writing of the input and output buffers, so we won't take
	 * that shortcut here. */
	struct evbuffer *input =  bufferevent_get_input(bev);
	line = evbuffer_readln(input, &n, EVBUFFER_EOL_CRLF);
	char cmd[256], protocol[256], path[MAX_PATH_SIZE];
	httpHeader_t httpHeader;
	httpHeader.command = UNKNOWN_C;
	httpHeader.status = OK;
	if (n != 0) {
		int scaned = sscanf(line, "%s %s %s\n", cmd, path, protocol);
		if (scaned == 3) {
			if (!strcmp(cmd, "GET")) {
				httpHeader.command = GET;
			}
			else if (!strcmp(cmd, "HEAD")) {
				httpHeader.command = HEAD;
			}
			else { 
				httpHeader.command = UNKNOWN_C;
			}
		/*	if (strcmp(protocol, "HTTP/1.1")) {
				printf("BAD PROTOCOL%s\n", protocol);
				httpHeader.status = BAD_REQUEST;
			}*/
			if (path[0] != '/') {
				printf("BAD INPUtT\n");
				httpHeader.status = BAD_REQUEST;
			}
			urlDecode(path);
			httpHeader.type = getContentType(path);
			if (getDepth(path) == -1) {
				printf("BAD DEPTH\n");
				httpHeader.status = BAD_REQUEST;
			}
		}
		else {
			printf("Bad scanned\n");
			httpHeader.status = BAD_REQUEST;
		}
	}
	else {
		printf("OOO BAD N\n");
		httpHeader.status = BAD_REQUEST;
	}
	switch (httpHeader.status) {
		case BAD_REQUEST:
			printf("Bad request\n");
			break;
		case OK:
			printf("OK\n");
			break;
		case NOT_FOUND:
			printf("NOt found\n");
			break;
	}
	switch (httpHeader.command) {
		case UNKNOWN_C:
			printf("UNKNOWS\n");
			break;
		case GET:
			printf("GET\n");
			break;
		case HEAD:
			printf("HEAD\n");
			break;
	}
	printf("%s\n", path);
	free(line);
	if (httpHeader.status != BAD_REQUEST) {
		char fullPath[2048] = {'\0'};
		strcpy(fullPath, ROOT_PATH);
		strcat(fullPath, path);
		int fd = open(fullPath, O_RDONLY);
		if (fd < 0) {
			httpHeader.status = NOT_FOUND;
			printf("Can't open %s", fullPath);
		}
		client->openFd = -1;
		struct stat st;
		httpHeader.length = lseek(fd, 0, SEEK_END);
		if (httpHeader.length == -1 || lseek(fd, 0, SEEK_SET) == -1) {
			httpHeader.status = BAD_REQUEST;
			printf("Cant seek\n");
		}
		addHeader(&httpHeader, client->output_buffer);
		if (fstat(fd, &st) < 0) {
			perror("fstat");
		}
		if (fd != -1 && httpHeader.status == OK && httpHeader.command == GET) {
			evbuffer_set_flags(client->output_buffer, EVBUFFER_FLAG_DRAINS_TO_FD);
			if(evbuffer_add_file(client->output_buffer, fd, 0, httpHeader.length) != 0) {
				perror("add file");
			}
		}
	//	printf("%d\n", fd);
	}

	//evbuffer_add(client->output_buffer, "AAA", 3);
	/*
	while ((line = evbuffer_readln(input, &n, EVBUFFER_EOL_CRLF))) {
		evbuffer_add(client->output_buffer, line, n);
		evbuffer_add(client->output_buffer, "\n", 1);
		free(line);
	}*/
	//evbuffer_add_printf(client->output_buffer, "HTTP/1.1 200 OK\r\rContent-Type: text/html\r\nDate: Sun, 14 Sep 2014 08:39:53 GMT\r\nContent-Length: 5\r\n\r\n OKK\r\n");
	//  while (evbuffer_get_length(input) > 0) {
	/* Remove a chunk of data from the input buffer, copying it into our
	 * local array (data). */
	//    nbytes = evbuffer_remove(input, data, 4096); 
	/* Add the chunk of data from our local array (data) to the client's
	 * output buffer. */
	//  evbuffer_add(client->output_buffer, data, nbytes);

	//}

	/* Send the results to the client.  This actually only queues the results
	 * for sending. Sending will occur asynchronously, handled by libevent. */
	if (bufferevent_write_buffer(bev, client->output_buffer) == -1) {
		errorOut("Error sending data to client on fd %d\n", client->fd);
	}

	//bufferevent_setcb(bev, NULL, buffered_on_write, NULL, NULL);
	//bufferevent_enable(bev, EV_WRITE);
}
Ejemplo n.º 4
0
static void static_files_cb(struct evhttp_request *req, void *arg)
{
    http_serverlog_request(req);
    const char *static_root = arg;
    apr_pool_t *local_pool;
    const char *full_name;
    struct stat64 file_stat;
    const char *mime_type;

    if(!static_root)
    {
        LOG4C_ERROR(logger, "static root not configured");
        evhttp_send_error(req, HTTP_NOTFOUND, "Static file server not configured");
        return;
    }

    const char *uri = evhttp_request_get_uri(req);

    if (strstr(uri, "..") != NULL)
    {
        LOG4C_ERROR(logger, "illegal URL");
        evhttp_send_error(req, HTTP_BADREQUEST, "Illegal URL");
        return;
    }

    CREATE_POOL(local_pool, NULL);

    const char *path = get_path_from_uri(local_pool, uri);

    mime_type = guess_mime_type(uri);

    LOG4C_DEBUG(logger, "mime type is %s", mime_type);

    full_name = apr_pstrcat(local_pool, static_root, "/", path, NULL);

    if (lstat64(full_name, &file_stat) < 0)
    {
        LOG4C_ERROR(logger, "file not found");
        evhttp_send_error(req, HTTP_NOTFOUND, NULL);
        return;
    }

    int fd = open(full_name, O_RDONLY);
    if (fd < 0)
    {
        LOG4C_ERROR(logger, "open failed");
        evhttp_send_error(req, HTTP_NOTFOUND, NULL);
        return;
    }

    struct evbuffer *rep_buf = evbuffer_new();

    evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", mime_type);
    evbuffer_set_flags(rep_buf, EVBUFFER_FLAG_DRAINS_TO_FD);
    //TODO: LIBEVENT DOES NOT SUPPORT LARGE FILES - USES off_t BUT _FILE_OFFSET_BITS=64 IS NOT DEFINED!
    evbuffer_add_file(rep_buf, fd, 0, file_stat.st_size); //
    evhttp_send_reply(req, HTTP_OK, "OK", rep_buf);

    evbuffer_free(rep_buf);

    RELEASE_POOL(local_pool);
}