示例#1
0
ssize_t sock_recv(int fd, char *buf, size_t size)
{
    coro_sock *sock = find_sock_by_fd(fd);
    // 一个socket可能被多个协程持有,而这多个持有当前socket的协程,可能
    // 当前并没有阻塞再这个socket上,考虑如下情况,某个持有当前socket的协程
    // 释放了这个socket对象,那么,当某个持有这个socket的协程在使用这个socket的
    // 时候,就可能无法通过fd反查socket了
    // 所以,这里要重新尝试获取socket,判断socket对象是否有效
    // 这里可能会有bug产生,因为fd是每次取最小的,如果close掉了,立马又创建了一个socket
    // 那么2个fd是重复,因此,完善的解决方案大概是这样子的
    // 但是这个情况在非协程环境也是存在的,因此,不做针对他的特殊处理了
    if ( !sock ) {
        return -1;
    }
    sock->op = READING;
    ssize_t status = 0;
    // 调用sock_recv的时候,还没有进行yield
    // 所以,当前协程就是持有当前socket对象的协程
    // 因此,我们可以把当前协程加到socket的持有协程里面去
    uthread_t cur = coro_current_uthread();
    if ( TEST_WAIT_READ(sock->status) ) {
        if ( TEST_EOF(sock->status) ) {
            status = -1;
            // SET_EOF(sock->status);
        }
        else {
            // 如果当前socket在等待读
            // 那么说明当前协程已经无法继续往下执行了,
            //  1. 协程会阻塞在当前socket的读队列里面
            //  2. socket被阻塞在当前协程
            //  发生了阻塞,那么我们需要切换到其他的协程上去,放弃继续执行机会
            set_pending_status(sock, set_wait_read_status, cur, set_wait_read_status);
            sock->readqueue->push(cur);
            status = coro_schedule_uthread(cur, 0);
        }
    }
    // 执行到这里,说明我们完成了IO操作
    // 那么说明,我们的协程当前一定没有被阻塞,所以移除阻塞标志

    // 假设read被阻塞了,那么,执行到这里一定是经历过调度,然后回来的
    // 那么,我们就无法保证这个sock指针还是有效的,因为他可能被释放过了
    // 因此这里要重新获取sock指针

    ssize_t ret = status;
    sock = find_sock_by_fd(fd);
    if ( ret >= 0 && sock ) {

        bufferevent * bev = sock->bev;
        struct evbuffer *input;
        input = bufferevent_get_input(bev);
        int n = evbuffer_remove(input, buf, size);
        // 无论如何,我们都认为这次read已经结束了
        clear_pending_status(sock, cur);
        // 如果inputbuffer还有剩余空间,那么我们留下可读标记
        if ( n >= 0 && evbuffer_get_length(input) > 0 ) {
            SET_READ(sock->status);
        }
        else {
            SET_WAIT_READ(sock->status);
        }
        ret = (n >= 0 ? n : -1);
    }
    return ret;
}
示例#2
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);
}
示例#3
0
int netstring_read_evbuffer(struct bufferevent *bev, netstring_t **netstring)
{
    int bytes, offset;
    size_t read_len;
    char *temp_buffer;
    temp_buffer = NULL;
    offset = 0;
    struct evbuffer *ib = bufferevent_get_input(bev);

    if (*netstring == NULL) {
        /* No buffer yet. Peek at first 10 bytes, to get length and colon. */
        unsigned char *lenstr;
        int i, len;
        struct evbuffer_ptr *search_end = pkg_malloc(sizeof(struct evbuffer_ptr));
        CHECK_MALLOC(search_end);

        i = evbuffer_get_length(ib);
        len = ((NETSTRING_PEEKLEN <= i) ? (NETSTRING_PEEKLEN) : (i-1));
        evbuffer_ptr_set(ib, search_end, len, EVBUFFER_PTR_SET);
        struct evbuffer_ptr loc = evbuffer_search_range(ib, ":", 1, NULL, search_end);
        pkg_free(search_end);
        if (loc.pos < 0) {
            // no colon found
            if (i > NETSTRING_PEEKLEN)
                return NETSTRING_ERROR_TOO_LONG;
            // TODO: peek at what's available and return suitable errors
            return NETSTRING_INCOMPLETE;
        }


        lenstr = pkg_malloc(loc.pos+1);
        CHECK_MALLOC(lenstr);
        bytes = evbuffer_remove(ib, lenstr, loc.pos+1);

        /* First character must be a digit */
        if (!isdigit(lenstr[0]))
            return NETSTRING_ERROR_NO_LENGTH;

        /* No leading zeros allowed! */
        if (lenstr[0] == '0' && isdigit(lenstr[1]))
            return NETSTRING_ERROR_LEADING_ZERO;
        if (lenstr[loc.pos] != ':') {
            return NETSTRING_ERROR_NO_COLON;
        }
        len = i = 0;

        /* Read the number of bytes */
        for (i = 0; i < loc.pos; i++) {
            /* Accumulate each digit, assuming ASCII. */
            len = len*10 + (lenstr[i] - '0');
        }
        pkg_free(lenstr);
        /* alloc the memory needed for the whole netstring */
        read_len = len+1;
        temp_buffer = pkg_malloc(read_len);
        CHECK_MALLOC(temp_buffer);

        /* initialize the netstring struct */
        *netstring = pkg_malloc(sizeof(netstring_t));
        CHECK_MALLOC(netstring);
        (*netstring)->read = 0;
        (*netstring)->length = len;
        (*netstring)->buffer = temp_buffer;
        (*netstring)->string = NULL;
    } else {
        /* Continue reading into an existing buffer. */
        offset = (*netstring)->read;
        read_len = (*netstring)->length-offset+1;
        temp_buffer = (*netstring)->buffer + offset;
    }

    /* Read from the evbuffer */
    bytes = evbuffer_remove(ib, temp_buffer, read_len);
    int total = (*netstring)->read += bytes;

    /* See if we have the whole netstring yet */
    if (read_len > bytes) {
        return NETSTRING_INCOMPLETE;
    }

    /* Test for the trailing comma */
    if (((*netstring)->buffer)[total-1] != ',') {
        return NETSTRING_ERROR_NO_COMMA;
    }

    /* Replace the comma with \0 */
    (*netstring)->buffer[total-1] = '\0';

    /* Set the string pointer to the "body" of the netstring */
    (*netstring)->string = (*netstring)->buffer;
    return 0;
}
示例#4
0
void TS3::telnetMessage(bufferevent *bev, void *parentPtr)
{
	auto parent = static_cast<TS3*>(parentPtr);
	std::string s;
	char buf[1024];
	int n;
	evbuffer *input = bufferevent_get_input(bev);
	while ((n = evbuffer_remove(input, buf, sizeof(buf))) > 0)
		s.append(buf, n);

	// trim CR LF
	if (s.size() > 2)
		s.erase(s.size() - 2);
	else
		LOG(ERROR) << "Received telnet line that is too short!";

	// Pong messages clutter INFO log badly
	// LOG(INFO) << s;

	switch (parent->_sqState)
	{
	case TS3::State::NotConnected:
		// FIXME: very poor criteria for connection
		static const std::string welcome = "Welcome to the TeamSpeak 3 ServerQuery interface";
		if (s.find(welcome) != s.npos)
		{
			LOG(INFO) << "Connected to ServerQuery interface";
			parent->_sqState = TS3::State::ServerQueryConnected;
			evbuffer_add_printf(bufferevent_get_output(bev), "login %s %s\n",
								parent->GetRawConfigValue("Teamspeak.Login").c_str(),
								parent->GetRawConfigValue("Teamspeak.Password").c_str());
		}
		break;

	case TS3::State::ServerQueryConnected:
		static const std::string okMsg = "error id=0 msg=ok";
		if (beginsWith(s, okMsg))
		{
			LOG(INFO) << "Authorized on TS3 server";
			parent->_sqState = TS3::State::Authrozied;
			evbuffer_add_printf(bufferevent_get_output(bev), "use port=9987\n");
		}
		break;

	case TS3::State::Authrozied:
		if (beginsWith(s, okMsg))
		{
			LOG(INFO) << "Connected to Virtual Server";
			parent->_sqState = TS3::State::VirtualServerConnected;
			evbuffer_add_printf(bufferevent_get_output(bev), "clientupdate client_nickname=%s\n", parent->_nickname.c_str());
		}
		break;

	case TS3::State::VirtualServerConnected:
		if (beginsWith(s, okMsg))
		{
			LOG(INFO) << "Nickname is set";
			parent->_sqState = TS3::State::NickSet;
			evbuffer_add_printf(bufferevent_get_output(bev), "servernotifyregister event=server\n");
		}

		break;

	case TS3::State::NickSet:
		if (beginsWith(s, okMsg))
		{
			LOG(INFO) << "Subscribed to connects/disconnects";
			parent->_sqState = TS3::State::Subscribed;
			evbuffer_add_printf(bufferevent_get_output(bev), "servernotifyregister event=textchannel id=%ld\n", parent->_channelID);
		}
		break;

	case TS3::State::Subscribed:
		if (beginsWith(s, "notifycliententerview"))
		{
			auto tokens = tokenize(s, ' ');
			try {
				parent->TS3Connected(tokens.at(4).substr(5), tokens.at(6).substr(16));
			} catch (std::exception &e) {
				LOG(ERROR) << "Can't parse message: \"" << s << "\" | Exception: " << e.what();
			}
			break;
		}

		if (beginsWith(s, "notifyclientleftview"))
		{
			auto tokens = tokenize(s, ' ');
			try {
				parent->TS3Disconnected(tokens.at(5).substr(5, tokens.at(5).size() - 5));
			} catch (std::exception &e) {
				LOG(ERROR) << "Can't parse message: \"" << s << "\" | Exception: " << e.what();
			}
			break;
		}

		if (beginsWith(s, "notifytextmessage"))
		{
			auto tokens = tokenize(s, ' ');
			try {
				auto nick = ReplaceTS3Spaces(tokens.at(4).substr(12));
				auto message = ReplaceTS3Spaces(tokens.at(2).substr(4));
				parent->TS3Message(nick, message);
			} catch (std::exception &e) {
				LOG(ERROR) << "Can't parse message: \"" << s << "\" | Exceptions: " << e.what();
			}
			break;
		}

		break;
	}

}
示例#5
0
// a part of input data is received
static void s3http_client_read_cb (struct bufferevent *bev, void *ctx)
{
    S3HttpClient *http = (S3HttpClient *) ctx;
    struct evbuffer *in_buf;

    in_buf = bufferevent_get_input (bev);
    
    if (http->response_state == S3R_expected_first_line) {
        if (!s3http_client_parse_first_line (http, in_buf)) {
            g_free (http->response_code_line);
            http->response_code_line = NULL;
            LOG_debug (HTTP_LOG, "More first line data expected !");
            return;
        }
        LOG_debug (HTTP_LOG, "Response:  HTTP %d.%d, code: %d, code_line: %s", 
                http->major, http->minor, http->response_code, http->response_code_line);
        http->response_state = S3R_expected_headers;
    }

    if (http->response_state == S3R_expected_headers) {
        if (!s3http_client_parse_headers (http, in_buf)) {
            LOG_debug (HTTP_LOG, "More headers data expected !");
            s3http_client_free_headers (http->l_input_headers);
            http->l_input_headers = NULL;
            return;
        }

        LOG_debug (HTTP_LOG, "ALL headers received !");
        http->response_state = S3R_expected_data;
    }

    if (http->response_state == S3R_expected_data) {
        // add input data to the input buffer
        http->input_read += evbuffer_get_length (in_buf);
        evbuffer_add_buffer (http->input_buffer, in_buf);
        // LOG_debug (HTTP_LOG, "INPUT buf: %zd bytes", evbuffer_get_length (http->input_buffer));
        

        // request is fully downloaded
        if (http->input_read >= http->input_length) {
            LOG_debug (HTTP_LOG, "DONE downloading last chunk, in buf size: %zd !", evbuffer_get_length (http->input_buffer));

            // inform client that a end of data is received
            if (http->on_last_chunk_cb)
                http->on_last_chunk_cb (http, http->input_buffer, http->cb_ctx);

            http->response_state = S3R_expected_first_line;
            // rest
            s3http_client_request_reset (http);
            // inform pool client
            // XXX:
            /*
            if (http->on_request_done_pool_cb)
                http->on_request_done_pool_cb (http, http->pool_cb_ctx);
            */
        // only the part of it
        } else {
            // inform client that a part of data is received
            if (http->on_chunk_cb)
                http->on_chunk_cb (http, http->input_buffer, http->cb_ctx);
            }
    }
}
示例#6
0
void client_event_read(struct bufferevent *bev, void *arg)
{
    log_debug("client_event_read");
    client_t *c = (client_t*) arg;
    server_t *s = c->server;
    log_debug("Received read event from client socket %d", c->socket);

    if(c->msg == NULL)
    {
        c->msg = msg_init(c->worker->msg_buf);
    }

    int res = evbuffer_add_buffer(c->evbuf, bufferevent_get_input(bev));
    char *line;

    while((line = evbuffer_readln(c->evbuf, NULL, EVBUFFER_EOL_CRLF)) != NULL)
    {
        log_debug("Read data : %s", line);
        decode_result res = decoder_run(c->msg, line);
        msg_print(c->msg);

        switch(res)
        {
            case DR_ERR_FORMAT:
                client_increase_req_err(c);
                worker_increase_req_err(c->worker);
                msg_clean(c->msg);
                log_debug("Wrong message format : %s", line);
                resp_error_wrong_msg_format(c->worker->msg_buf, c->socket);
                break;

            case DR_ERR_PARAM_FORMAT:
                client_increase_req_err(c);
                worker_increase_req_err(c->worker);
                msg_clean(c->msg);
                log_debug("Wrong parameter format : %s", line);
                resp_error_param_format(c->worker->msg_buf, c->socket);
                break;

            case DR_OK:
                log_debug("Data OK.");
                break;

            default:
                break;
        }

        enum cmd_func_ret cmd_ret;

        switch(msg_get_stat(c->msg))
        {
            case MSG_STAT_DONE:
                log_debug("Message Done.");
                client_increase_req_ok(c);
                worker_increase_req_ok(c->worker);
                cmd_ret = command_proc(c, c->msg);
                if(cmd_ret != CMD_FUNC_DONE)
                {
                    c->req_ok++;
                    s->req_ok++;
                }
                msg_clean(c->msg);
                break;
        }


//        ic_trans_stat trans_stat = decoder_read_line(c, line);
//        log_debug("Trans stat : %d", trans_stat);
//        if(trans_stat == IC_TRANS_ALL_DONE)
//        {
//            log_debug("Trasfer done, ");
//        }
    }

}
示例#7
0
//处理读事件
void TcpHandler::dealReadEvent(int & success)
{
	//cout << "m_pLastNode addr is:  " << m_pLastNode <<endl;
	if(m_pLastNode)
	{
		//cout << "m_pLastNode msglen is:  "<< m_pLastNode->m_nMsgLen <<endl;
		//cout << "m_pLastNode m_nOffSet is: " << m_pLastNode->m_nOffSet <<endl;
	}
	else
	{
		//cout << "m_pLastNode addr is null!!!" <<endl;
	}
	

	evbuffer * inputBuf = bufferevent_get_input(m_pBufferevent);
	size_t inputLen = evbuffer_get_length(inputBuf);
	//cout <<"total len is : "<<  inputLen <<endl;
	while(inputLen > 0)
	{
		//tcphandler第一次接收消息或者该node接收完消息,需要开辟新的node接受消息
		if(!m_pLastNode || m_pLastNode->m_nMsgLen <= m_pLastNode->m_nOffSet)
		{
			//判断消息长度是否满足包头大小,不满足跳出
			if(inputLen  < PACKETHEADLEN)
			{
				break;
			}

			char data[PACKETHEADLEN]  = {0};
			bufferevent_read(m_pBufferevent, data, PACKETHEADLEN);
			struct PacketHead  packetHead;

			memcpy(&packetHead, data, PACKETHEADLEN);

			cout << "packetId is : " <<packetHead.packetID << endl;

			cout << "packetLen is :  " << packetHead.packetLen << endl;
			
			if(packetHead.packetID > 1024 || packetHead.packetID < 0)
			{
				success = 0;
				return;
			}

			insertNode(packetHead.packetID, packetHead.packetLen);

			inputLen -= PACKETHEADLEN;
			//cout << "after remove head the length is : " << inputLen <<endl;
		}

		//考虑可能去包头后剩余的为0
		if(inputLen <= 0)
		{
			break;
		}
		//读取去除包头后剩余消息
		
		tcpRead(inputLen);
	}

	
}
示例#8
0
文件: net.c 项目: libbtc/libbtc
void read_cb(struct bufferevent* bev, void* ctx)
{
    struct evbuffer* input = bufferevent_get_input(bev);
    if (!input)
        return;

    size_t length = evbuffer_get_length(input);

    btc_node *node = (btc_node *)ctx;

    // expand the cstring buffer if required
    cstr_alloc_minsize(node->recvBuffer, node->recvBuffer->len+length);

    // copy direct to cstring, avoid another heap buffer
    evbuffer_copyout(input, node->recvBuffer->str+node->recvBuffer->len, length);
    node->recvBuffer->len += length;

    // drain the event buffer
    evbuffer_drain(input, length);

    struct const_buffer buf = {node->recvBuffer->str, node->recvBuffer->len};
    btc_p2p_msg_hdr hdr;
    char *read_upto = NULL;

    do {
        //check if message is complete
        if (buf.len < BTC_P2P_HDRSZ)
        {
            break;
        }

        btc_p2p_deser_msghdr(&hdr, &buf);
        if (buf.len < hdr.data_len)
        {
            //if we haven't read the whole message, continue and wait for the next chunk
            break;
        }
        if (buf.len >= hdr.data_len)
        {
            //at least one message is complete

            struct const_buffer cmd_data_buf = {buf.p, buf.len};
            btc_node_parse_message(node, &hdr, &cmd_data_buf);

            //skip the size of the whole message
            buf.p += hdr.data_len;
            buf.len -= hdr.data_len;

            read_upto = (void *)buf.p;
        }
        if (buf.len == 0)
        {
            //if we have "consumed" the whole buffer
            node->recvBuffer->len = 0;
            break;
        }
    } while(1);

    if (read_upto != NULL && node->recvBuffer->len != 0 && read_upto != (node->recvBuffer->str + node->recvBuffer->len))
    {
        char *end = node->recvBuffer->str + node->recvBuffer->len;
        size_t available_chunk_data = end - read_upto;
        //partial message
        cstring *tmp = cstr_new_buf(read_upto, available_chunk_data);
        cstr_free(node->recvBuffer, true);
        node->recvBuffer = tmp;
    }
}
示例#9
0
void ClientImpl::regularReadCallback(struct bufferevent *bev) {
    struct evbuffer *evbuf = bufferevent_get_input(bev);
    boost::shared_ptr<CxnContext> context = m_contexts[bev];
    int32_t remaining = static_cast<int32_t>(evbuffer_get_length(evbuf));
    bool breakEventLoop = false;

    if (context->m_lengthOrMessage && remaining < 4) {
        return;
    }

    while (true) {
        if (context->m_lengthOrMessage && remaining >= 4) {
            char lengthBytes[4];
            ByteBuffer lengthBuffer(lengthBytes, 4);
            evbuffer_remove( evbuf, lengthBytes, 4);
            context->m_nextLength = static_cast<size_t>(lengthBuffer.getInt32());
            context->m_lengthOrMessage = false;
            remaining -= 4;
        } else if (remaining >= context->m_nextLength) {
            boost::shared_array<char> messageBytes = boost::shared_array<char>(new char[context->m_nextLength]);
            context->m_lengthOrMessage = true;
            evbuffer_remove( evbuf, messageBytes.get(), static_cast<size_t>(context->m_nextLength));
            remaining -= context->m_nextLength;
            InvocationResponse response(messageBytes, context->m_nextLength);
            boost::shared_ptr<CallbackMap> callbackMap = m_callbacks[bev];
            CallbackMap::iterator i = callbackMap->find(response.clientData());
            if(i != callbackMap->end()){
                try {
                    m_ignoreBackpressure = true;
                    breakEventLoop |= i->second->callback(response);
                    m_ignoreBackpressure = false;
                } catch (std::exception &e) {
                    if (m_listener.get() != NULL) {
                        try {
                            m_ignoreBackpressure = true;
                            breakEventLoop |= m_listener->uncaughtException( e, i->second, response);
                            m_ignoreBackpressure = false;
                        } catch (const std::exception& e) {
                            std::cerr << "Uncaught exception handler threw exception: " << e.what() << std::endl;
                        }
                    }
                }
                /*
                 * When Volt sends us out a notification, it comes with the ClientData
                 * filled in with a known 64-bit number.
                 * In this case, we don't want to remove the callback. We need a static
                 * callback here to continually process notifications.
                 */
                if(response.clientData() != VOLT_NOTIFICATION_MAGIC_NUMBER){
                    callbackMap->erase(i);
                    m_outstandingRequests--;
                }
            }

            //If the client is draining and it just drained the last request, break the loop
            if (m_isDraining && m_outstandingRequests == 0) {
                breakEventLoop = true;
            } else if (m_loopBreakRequested && (m_outstandingRequests <= m_maxOutstandingRequests)) {
                // ignore break requested until we have too many outstanding requests
                breakEventLoop = true;
            }
        } else {
            if (context->m_lengthOrMessage) {
                bufferevent_setwatermark( bev, EV_READ, 4, HIGH_WATERMARK);
            } else {
                bufferevent_setwatermark( bev, EV_READ, static_cast<size_t>(context->m_nextLength), HIGH_WATERMARK);
            }
            breakEventLoop |= (m_loopBreakRequested && (m_outstandingRequests <= m_maxOutstandingRequests));
            break;
        }
    }

    if (breakEventLoop) {
        event_base_loopbreak( m_base );
    }
}
示例#10
0
void NFCNet::conn_readcb(struct bufferevent *bev, void *user_data)
{
    //接受到消息
    NetObject* pObject = (NetObject*)user_data;
    if (!pObject)
    {
        return;
    }

    NFCNet* pNet = (NFCNet*)pObject->GetNet();
    if (!pNet)
    {
        return;
    }

    if (pObject->GetRemoveState())
    {
        return;
    }

    struct evbuffer *input = bufferevent_get_input(bev);
    if (!input)
    {
        return;
    }

    size_t len = evbuffer_get_length(input);

    //返回给客户端
    //  	struct evbuffer *output = bufferevent_get_output(bev);
    //  	evbuffer_add_buffer(output, input);
    //      SendMsg(1, strData,len, pObject->GetFd());
    //////////////////////////////////////////////////////////////////////////
    if (len > NFIMsgHead::NF_MSGBUFF_LENGTH)
    {
        char* strMsg = new char[len];

        if(evbuffer_remove(input, strMsg, len) > 0)
        {
            pObject->AddBuff(strMsg, len);
        }

        delete[] strMsg;
    }
    else
    {

        memset(pNet->mstrMsgData, 0, NFIMsgHead::NF_MSGBUFF_LENGTH);

        if(evbuffer_remove(input, pNet->mstrMsgData, len) > 0)
        {
            pObject->AddBuff(pNet->mstrMsgData, len);
        }
    }

    while (1)
    {
        int nDataLen = pObject->GetBuffLen();
        if (nDataLen > pNet->mnHeadLength)
        {
            if (!pNet->Dismantle(pObject))
            {
                break;
            }
        }
        else
        {
            break;
        }
    }
}
示例#11
0
static void
socks_read_cb(struct bufferevent *bev, void *ptr)
{
	obfsproxyssh_client_session_t *session = ptr;
	obfsproxyssh_t *state = session->client->state;
	struct evbuffer *buf;
	struct sockaddr_in addr;
	unsigned char *p, *userid;
	size_t len;
	int i;

	assert(bev == session->socks_ev);

	buf = bufferevent_get_input(bev);
	len = evbuffer_get_length(buf);
	if (len < SOCKS_4_CONNECT_REQUEST_LEN)
		return;

	p = evbuffer_pullup(buf, len);
	if (NULL == p) {
		log_f(state, "SOCKS: Error: %s Failed to pullup (OOM?)",
				bdata(session->socks_addr));
		goto out_free;
	}

	/*
	 * Parse the SOCKS 4 CONNECT
	 *
	 * uint8_4  VN  -> 4
	 * uint8_t  CN	-> 1
	 * uint16_t DSTPORT
	 * uint32_t DSTIP
	 * uint8_t  USERID[] (Tor PT arguments)
	 * uint8_t  NULL -> 0
	 */

	if (SOCKS_4_VER != p[0]) {
		log_f(state, "SOCKS: Error: %s Invalid SOCKS protocol version %d",
				bdata(session->socks_addr),
				p[0]);
		goto out_free;
	}

	if (SOCKS_4_CMD_CONNECT != p[1]) {
		log_f(state, "SOCKS: Error: %s Invalid SOCKS 4 command %d",
				bdata(session->socks_addr),
				p[1]);
		goto out_free;
	}

	userid = p + SOCKS_4_CONNECT_REQUEST_LEN;
	for (i = 0; i < len - SOCKS_4_CONNECT_REQUEST_LEN; i++) {
		if ('\0' == userid[i]) {
			if (len != SOCKS_4_CONNECT_REQUEST_LEN + i + 1) {
				log_f(state, "SOCKS: Error: %s Trailing garbage after CONNECT",
						bdata(session->socks_addr));
				goto out_free;
			}
			bufferevent_disable(bev, EV_READ);

			memset(&addr, 0, sizeof(addr));
			addr.sin_family = AF_INET;
			addr.sin_port = *(uint16_t *) (p + 2);
			addr.sin_addr.s_addr = *(uint32_t *) (p + 4);

			if (ssh_new_connection(session, &addr, (char *) userid))
				goto out_free;

			evbuffer_drain(buf, len);

			return;
		}
	}

	if (len > OBFSPROXYSSH_CLIENT_MAX_SOCKS_REQ) {
		log_f(state, "SOCKS: Error: %s SOCKS 4 Request too big",
				bdata(session->socks_addr));
		goto out_free;
	}
	return;

out_free:
	session_free(session);
	return;
}
示例#12
0
文件: http.c 项目: simonvik/xping
/*
 * Discard any data received. This is used after reading the response's
 * status line.
 */
static void
session_readcb_drain(struct bufferevent *bev, void *thunk)
{
	struct evbuffer *evbuf = bufferevent_get_input(bev);
	evbuffer_drain(evbuf, evbuffer_get_length(evbuf));
}
示例#13
0
/**
 * 客户端和远程服务器的交互
 */
void srv_bufferread_cb(struct bufferevent *bev, void *ptr)
{
    size_t n = 0;
    CTL_HEAD head;

    struct evbuffer *input = bufferevent_get_input(bev);
    struct evbuffer *output = bufferevent_get_output(bev);

    if ( evbuffer_remove(input, &head, CTL_HEAD_LEN) != CTL_HEAD_LEN)
    {
        st_d_print("读取数据包头%d错误!", CTL_HEAD_LEN);
        return;
    }

    if (!sd_id128_equal(head.mach_uuid, cltopt.session_uuid))
    {
        SYS_ABORT("服务端返回UUID校验失败:%s-%s",
                  SD_ID128_CONST_STR(head.mach_uuid), SD_ID128_CONST_STR(cltopt.session_uuid)); 
    }

    if (head.cmd == HD_CMD_ERROR) 
    {
        st_d_error("SERVER RETURNED ERROR!");
        exit(EXIT_SUCCESS);
    }

    if (head.cmd == HD_CMD_CONN_ACT)
    {
        P_PORTTRANS p_trans = sc_find_trans(head.extra_param); 
        if (!p_trans) 
        {
            SYS_ABORT("本地未找到连接信息:%d", head.extra_param);
        }

        bufferevent_enable(p_trans->local_bev, EV_READ|EV_WRITE);
        bufferevent_enable(p_trans->srv_bev, EV_READ|EV_WRITE); 

        st_d_print("开始传输数据:%d", head.extra_param); 
    }
    if (head.cmd == HD_CMD_END_TRANS) 
    {
        P_PORTTRANS p_trans = sc_find_trans(head.extra_param); 
        if (p_trans) 
        {
            st_d_print("EXTRA CLOSE TRANS: %d", head.extra_param);
            sc_free_trans(p_trans);
        }
    }
    if (head.cmd == HD_CMD_SS5_ACT) 
    {    
        // OK,返回给本地程序告知可以开始传输了
        // 这个绑定地址目前还没利用,主要是需要FTP这类需要带外传输另外连接端口的
        char ret_msg[10] = "\x05\x00\x00\x01\x00\x00\x00\x00\x10\x10";

        P_PORTTRANS p_trans = sc_find_trans(head.extra_param); 
        if (!p_trans) 
        {
            SYS_ABORT("本地SS5未找到连接信息:%d", head.extra_param);
        }

        bufferevent_enable(p_trans->local_bev, EV_READ|EV_WRITE);
        bufferevent_enable(p_trans->srv_bev, EV_READ|EV_WRITE); 

        bufferevent_write(p_trans->local_bev, ret_msg, sizeof(ret_msg));
        st_d_print("SS5准备传输数据:%d", head.extra_param); 

        return;
    }
    if (head.cmd == HD_CMD_CONN) 
    {
        assert(cltopt.C_TYPE == C_DAEMON);
        if (cltopt.C_TYPE == C_DAEMON) 
        {
            sc_find_daemon_portmap(head.daemonport, 1);
            P_PORTTRANS p_trans = sc_create_trans(head.extra_param); 
            p_trans->is_enc = 0;
            
            if (!p_trans)
            {
                st_d_error("本地无空闲TRANS!");
                return;
            }

            /*建立本地连接*/
            int local_fd = socket(AF_INET, SOCK_STREAM, 0);
            int reuseaddr_on = 1;
            if (setsockopt(local_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_on, 
                sizeof(reuseaddr_on)) == -1)
            {
                st_d_error("Reuse socket opt faile!\n");
                return;
            }
            struct sockaddr_in  local_srv;
            local_srv.sin_family = AF_INET;
            local_srv.sin_addr.s_addr = inet_addr("127.0.0.1");
            local_srv.sin_port = htons(head.daemonport);

            if (connect(local_fd, (struct sockaddr *)&local_srv, sizeof(local_srv))) 
            {
                st_d_error("连接本地端口%d失败!", head.daemonport); 
                return;
            }
            else
            {
                st_d_print("连接本地端口%d OK!", head.daemonport); 
            }


            /*建立服务器连接*/
            int srv_fd = socket(AF_INET, SOCK_STREAM, 0);
            if(sc_connect_srv(srv_fd) != RET_YES) 
            {
                st_d_error("连接服务器失败!");
                return;
            }


            struct event_base *base = bufferevent_get_base(bev);

            evutil_make_socket_nonblocking(local_fd);
            struct bufferevent *local_bev = 
                bufferevent_socket_new(base, local_fd, BEV_OPT_CLOSE_ON_FREE);
            bufferevent_setcb(local_bev, bufferread_cb, NULL, bufferevent_cb, p_trans);
            //bufferevent_enable(local_bev, EV_READ|EV_WRITE);

            evutil_make_socket_nonblocking(srv_fd); 
            struct bufferevent *srv_bev = 
                bufferevent_socket_new(base, srv_fd, BEV_OPT_CLOSE_ON_FREE);
            bufferevent_setcb(srv_bev, bufferread_cb, NULL, bufferevent_cb, p_trans);
            //bufferevent_enable(srv_bev, EV_READ|EV_WRITE);


            p_trans->l_port = head.extra_param;
            p_trans->local_bev = local_bev;
            p_trans->srv_bev = srv_bev;

            /* 向服务器报告连接请求 */
            // 必须要发送CONN包,触发这个连接转移到线程池处理  
            CTL_HEAD ret_head;
            memset(&ret_head, 0, CTL_HEAD_LEN);
            ret_head.cmd = HD_CMD_CONN;
            ret_head.extra_param = p_trans->l_port; 
            ret_head.mach_uuid = cltopt.session_uuid;
            ret_head.direct = DAEMON_USR; 

            bufferevent_write(srv_bev, &ret_head, CTL_HEAD_LEN);

            st_d_print("DAEMON端准备OK!");
        }
    }

}
示例#14
0
void BaseServer::read_callback(bufferevent *pBufferEvent, void *user_data)
{

    evbuffer* inputbuf = bufferevent_get_input(pBufferEvent);
    evbuffer* outputbuf = bufferevent_get_output(pBufferEvent);
    size_t t;
    std::string request;
    request=evbuffer_readln(inputbuf,&t,EVBUFFER_EOL_CRLF);
    printf("request= %s\n",request.c_str());
    std::vector<std::string> result;
    result = split(request," ");

    std::string http_method = result[0];
    std::string http_path   = result[1];
    std::string http_version= result[2];

    std::cout<<"method: "<<http_method<<std::endl;
    std::cout<<"path: "<<http_path<<std::endl;
    std::cout<<"http_version: "<<http_version<<std::endl;

    printf("path=%d\n",http_path.size());

    std::string content_type;
    auto pos = http_path.find(".jpg");
    if(std::string::npos==pos)
        content_type = "text/html\r\n";
    else
        content_type = "image/jpg\r\n";

    if(http_path=="/")
    {
        http_path="index.html";
    }
    else
    {
        http_path=http_path.substr(1);

    }


    std::ifstream ifile(http_path.c_str());
    if(ifile)
    {
        std::stringstream stream;
        stream << ifile.rdbuf();
        std::string filecontent(stream.str());
        ifile.close();
        stream.str("");
        stream<<"HTTP/1.1 200 OK\r\n"<<"Content-Type: "<<content_type
             <<"Content-Length: "<<filecontent.size()<<"\r\n\r\n";
        stream<<filecontent;
        std::string response(stream.str());
        stream.str("");
        //std::cout<<"response****"<<response;
        evbuffer_add(outputbuf,response.c_str(),response.size());
    }else
    {

    }




    evbuffer* tmp=evbuffer_new();
    evbuffer_add_buffer(tmp,inputbuf);
    evbuffer_free(tmp);




}
示例#15
0
void MessageManager::MessageDispatcher(struct bufferevent *bev, void *ctx)
{

	bufferevent_lock(bev);

	struct evbuffer *input = bufferevent_get_input(bev);
	evutil_socket_t socketFD = bufferevent_getfd(bev);

	uint32_t length = 0, evbufferLength;

	bool keepGoing = true;
	while(keepGoing)
	{
		evbufferLength = evbuffer_get_length(input);
		//If we don't even have enough data to read the length, just quit
		if(evbufferLength < sizeof(length))
		{
			keepGoing = false;
			continue;
		}

		//Copy the length field out of the message
		//	We only want to copy this data at first, because if the whole message hasn't reached us,
		//	we'll want the whole buffer still present here, undrained
		if(evbuffer_copyout(input, &length, sizeof(length)) != sizeof(length))
		{
			keepGoing = false;
			continue;
		}

		// Make sure the length appears valid
		// TODO: Assign some arbitrary max message size to avoid filling up memory by accident
		if(length < MESSAGE_MIN_SIZE)
		{
			LOG(WARNING, "Error parsing message: message too small.", "");
			evbuffer_drain(input, sizeof(length));
			keepGoing = false;
			continue;
		}

		//If we don't yet have enough data, then just quit and wait for more
		if(evbufferLength < length)
		{
			keepGoing = false;
			continue;
		}

		evbuffer_drain(input, sizeof(length));

		//Remove the length of the "length" variable itself
		length -= sizeof(length);
		char *buffer = (char*)malloc(length);

		if(buffer == NULL)
		{
			// This should never happen. If it does, probably because length is an absurd value (or we're out of memory)
			LOG(WARNING, "Error parsing message: malloc returned NULL. Out of memory?.", "");
			free(buffer);
			keepGoing = false;
			continue;
		}

		// Read in the actual message
		int bytesRead = evbuffer_remove(input, buffer, length);
		if(bytesRead == -1)
		{
			LOG(WARNING, "Error parsing message: couldn't remove data from buffer.", "");
		}
		else if((uint32_t)bytesRead != length)
		{
			LOG(WARNING, "Error parsing message: incorrect amount of data received than what expected.", "");
		}

		MessageEndpointLock endpoint = MessageManager::Instance().GetEndpoint(socketFD);
		if(endpoint.m_endpoint != NULL)
		{
			Message *message = Message::Deserialize(buffer, length);
			if(!endpoint.m_endpoint->PushMessage(message))
			{
				LOG(DEBUG, "Discarding message. Error in pushing it to a queue.", "");
			}
		}
		else
		{
			LOG(DEBUG, "Discarding message. Received it for a non-existent endpoint.", "");
		}

		free(buffer);
	}

	bufferevent_unlock(bev);
}
示例#16
0
static char *read_line(struct bufferevent *bev, size_t *n)
{
	return evbuffer_readln(bufferevent_get_input(bev),
			       n, EVBUFFER_EOL_CRLF_STRICT);
}
示例#17
0
void createResponse(bufferevent *pBufferEvent)
{
    struct evbuffer* pInputBuffer = bufferevent_get_input(pBufferEvent);
    struct evbuffer* pOutputBuffer = bufferevent_get_output(pBufferEvent);

    char *line;
    size_t size = 0;
    line = evbuffer_readln(pInputBuffer, &size, EVBUFFER_EOL_CRLF);

    std::string Request = std::string(line);
    //std::cout << Request << "\n";

    //read method and path
    size_t nMethodEnd = Request.find(" ");
    std::string sMethod = std::string(Request, 0, nMethodEnd);
    //std::cout << sMethod << "\n";

    size_t nPathEnd = Request.find(" ", nMethodEnd+1);
    std::string sRawPath = std::string(Request, nMethodEnd+1, nPathEnd-nMethodEnd-1);
    //std::cout << sRawPath << "\n";

    size_t nDelimPos = sRawPath.find('?');
    std::string sHalfRawPath = sRawPath.substr(0, nDelimPos);
    //std::cout << sHalfRawPath << "\n";
    char* sTempPath = new char[sHalfRawPath.length()+1]; // at most the same size + term\0
    urlDecode(sTempPath, sHalfRawPath.c_str());
    std::string sPath = std::string(sTempPath);
    //std::cout << sPath << "\n";

    if (Request.find(" ", nPathEnd+1) != std::string::npos) { // extra spaces in request
        //std::cout << "ERROR: extra spaces\n";
        writeHeader(pOutputBuffer, STATUS_BAD_REQUEST, TYPE_HTML, MASSAGE_LENGTH_BAD_REQUEST);
        evbuffer_add(pOutputBuffer, MASSAGE_BAD_REQUEST, MASSAGE_LENGTH_BAD_REQUEST);
        return;
    }

    //Validate path
    if(!validatePath(sPath))
    {
        //std::cout << "Warning: forbidden path\n";
        writeHeader(pOutputBuffer, STATUS_FORBIDDEN, TYPE_HTML, MASSAGE_LENGTH_FORBIDDEN);
        evbuffer_add(pOutputBuffer, MASSAGE_FORBIDDEN, MASSAGE_LENGTH_FORBIDDEN);
        return;
    }
    //std::cout << "Ok: path ok\n";



    //find target file
    std::string sRealPath = std::string(DOCUMENT_ROOT);
    sRealPath.append(std::string(sPath));

    bool bIndex = false;
    if (sRealPath[sRealPath.length()-1] == '/') {
        //std::cout << "Ok: index\n";
        sRealPath.append("index.html");
        bIndex = true;
    }

    int fFile = open(sRealPath.c_str(), O_NONBLOCK|O_RDONLY);
    if (fFile == -1) {
        //std::cout << "Warning: file not opened\n";
        if (bIndex) {
            writeHeader(pOutputBuffer, STATUS_FORBIDDEN, TYPE_HTML, MASSAGE_LENGTH_FORBIDDEN);
            evbuffer_add(pOutputBuffer, MASSAGE_FORBIDDEN, MASSAGE_LENGTH_FORBIDDEN);
        } else {
            writeHeader(pOutputBuffer, STATUS_NOT_FOUND, TYPE_HTML, MASSAGE_LENGTH_NOT_FOUND);
            evbuffer_add(pOutputBuffer, MASSAGE_NOT_FOUND, MASSAGE_LENGTH_NOT_FOUND);
        }
        return;
    }
    //std::cout << "Ok: file opened\n";

    struct stat FileStats;
    fstat(fFile, &FileStats);
    if(!strcmp(sMethod.c_str(), METHOD_GET)) {
        //std::cout << "Ok: method \"get\"\n";
        writeHeader(pOutputBuffer, STATUS_OK, getContentType(sRealPath), FileStats.st_size);
        evbuffer_add_file(pOutputBuffer, fFile, 0, FileStats.st_size);
    } else if(!strcmp(sMethod.c_str(), METHOD_HEAD)){
        //std::cout << "Ok: method \"head\"\n";
        // ctime gives only /n so we'll add proper CRLF
        writeHeader(pOutputBuffer, STATUS_OK, getContentType(sRealPath), FileStats.st_size);
        evbuffer_add(pOutputBuffer, CRLF, 2);
    } else {
        writeHeader(pOutputBuffer, STATUS_BAD_REQUEST, TYPE_HTML, MASSAGE_LENGTH_BAD_REQUEST);
        evbuffer_add(pOutputBuffer, MASSAGE_BAD_REQUEST, MASSAGE_LENGTH_BAD_REQUEST);
    }
    return;
}
示例#18
0
/* Функция обратного вызова для события: данные готовы для чтения в buf_ev */
static void echo_read_cb(struct bufferevent *buf_ev, void *arg) {
    struct evbuffer *buf_input = bufferevent_get_input(buf_ev);
    struct evbuffer *buf_output = bufferevent_get_output(buf_ev);

    size_t length = evbuffer_get_length(buf_input);

    char recvBuf[10000];

    evbuffer_copyout(buf_input, recvBuf, length);
    recvBuf[length] = '\0';

    std::istringstream split(recvBuf);
    std::string sRequestFileName;
    for (std::string token; std::getline(split, token);) {
        if (token.find("GET ") != std::string::npos) {
            std::istringstream ss(token);
            std::getline(ss, sRequestFileName, ' '); // GET
            std::getline(ss, sRequestFileName, ' '); // fname
        }
    }

    if (sRequestFileName.empty()) {
        std::cout << "invalid request" << std::endl;
        //onDisconnect();
        bufferevent_free(buf_ev);

        return;
    }

    std::cout << "GET " << sRequestFileName << std::endl;

    std::string sUsedFileName;
    if (sRequestFileName == "/")
        sUsedFileName = "/index.html";
    else {
        std::stringstream ss(sRequestFileName);
        std::getline(ss, sUsedFileName, '?');
        //sUsedFileName = sRequestFileName;
    }


    FILE *f = fopen((mainDir + sUsedFileName).c_str(), "r");

    if (f == NULL) { // 404
        std::cout << "No page " << (mainDir + sUsedFileName) << ", disconnecting." << std::endl;

        //std::string s404 = "HTTP/1.1 404 Not Found\r\n\r\n";
        std::string s404 = "HTTP/1.0 404 Not Found\r\nContent-Length: 0\r\nContent-Type: text/html\r\n\r\n";
/*			std::string s404 = "HTTP/1.1 ";
			s404 += sRequestFileName;
			const char sz404page[] = "<html><body>404 Page not found :(</html></body>";
			s404 += " 404 Not Found\r\nContent-Type: text/html;charset=win-1251\r\nContent-Length: ";
			s404 += std::to_string(sizeof(sz404page));
			s404 += "\r\nCache - Control: no - cache, no - store\r\n\r\n";
			s404 += sz404page;*/

        //send(m_sock, s404.c_str(), s404.length(), 0);
        bufferevent_write(buf_ev, s404.c_str(), s404.length());
        std::cout << s404 << std::endl;
        bufferevent_flush(buf_ev, EV_WRITE, BEV_NORMAL);

        //onDisconnect();

        //bufferevent_free(buf_ev);

        return;
    }

    long lSize = 0;
    if (fseek(f, 0, SEEK_END) == 0) {
        lSize = ftell(f);
        fseek(f, 0, SEEK_SET);
    }

    char *pBuf = new char[lSize + 1];

    if (fread(pBuf, lSize, 1, f) != 1) { // read error
        delete[] pBuf;

        std::cout << "Read error, disconnecting." << std::endl;

        std::string s404 = "HTTP/1.1 ";
        s404 += sRequestFileName;
        const char sz404page[] = "<html><body>404 Page not found :(</html></body>";
        s404 += " 404 Not Found\r\nContent-Type: text/html;charset=win-1251\r\nContent-Length: ";
        s404 += std::to_string(sizeof(sz404page));
        s404 += "\r\nCache - Control: no - cache, no - store\r\n\r\n";
        s404 += sz404page;

        //send(m_sock, s404.c_str(), s404.length(), 0);
        bufferevent_write(buf_ev, s404.c_str(), s404.length());

        //onDisconnect();
        //bufferevent_free(buf_ev);

        fclose(f);
        return;
    };

    std::string sMsg = "HTTP/1.1 ";
    sMsg += sRequestFileName;
    sMsg += " 200 OK \r\nContent-Type: text/html;charset=win-1251\r\nContent-Length: ";

    //if( pBuf[1] != 'h' )
    //	sMsg += std::to_string(lSize + 12 + 14 - 1);
    //else
    sMsg += std::to_string(lSize - 1);
    sMsg += "\r\nCache - Control: no - cache, no - store\r\n\r\n";


    pBuf[lSize] = '\0';

//		if( pBuf[1] != 'h' )
//			sMsg += "<html><body>";
    sMsg += pBuf;
    sMsg.pop_back();
    delete[] pBuf;
    //if( pBuf[1] != 'h' )
    //	sMsg += "</body></html>";

    if (bufferevent_write(buf_ev, sMsg.c_str(), sMsg.length()) != 0) {
        std::cout << "Send fails, disconnecting." << std::endl;

        //onDisconnect();
        //bufferevent_free(buf_ev);

        fclose(f);
        return;
    }

    std::cout << "File " << sUsedFileName << " transferred." << std::endl;
    fclose(f);
}
示例#19
0
	Bool HawkGateThread::OnSessionRead(Session* pSession)
	{
		if (!pSession || pSession->Socket == INVALID_SOCKET)
			return false;		

		//检测输入缓冲区
		struct evbuffer* pBuf = bufferevent_get_input((bufferevent*)pSession->Event);
		if (!pBuf || !evbuffer_get_length(pBuf)) 
		{
			OnSessionError(pSession);
			return false;
		}

		//循环操作避免事件边缘触发引起的未读取问题
		while (evbuffer_get_length(pBuf))
		{
			m_pOctets->Clear();

			//读取数据
			Int32 iReadSize = evbuffer_remove(pBuf, m_pOctets->Begin(), (Size_t)m_pOctets->Capacity());
			if (iReadSize <= 0)
			{
				OnSessionError(pSession);
				return false;
			}
			m_pOctets->Resize(iReadSize);

			//调用性能监视器(只记流量, 解密前才是真实流量数据)
			if (m_pGateway->GetProfiler())
				m_pGateway->GetProfiler()->RegRecvProto(0, iReadSize);

			//解密
			if (pSession->ISecurity)
				pSession->ISecurity->Update(*m_pOctets);

			//填充到输入缓冲区
			UInt32 iFillPos = 0;
			UInt32 iBufSize = m_pOctets->Size();
			while(iBufSize)
			{
				//尽可能填充解码缓冲区
				UInt32 iFillSize = HawkMath::Min<UInt32>(pSession->IBuffer->EmptyCap(), iBufSize);
				if (iFillSize)
				{
					void* pData = (Char*)m_pOctets->Begin() + iFillPos;
					pSession->IBuffer->Insert(pSession->IBuffer->End(), pData, iFillSize);
					iFillPos += iFillSize;
					iBufSize -= iFillSize;
				}

				//检测是否可以解码输入缓冲区
				if (OnSessionDecode(pSession, pSession->IBuffer))
				{
					UInt32 iProtoSize = 0;
					while (P_ProtocolManager->CheckDecodeProtocol(*pSession->IBuffer, &iProtoSize))
					{
						Char* pProtoData = (Char*)pSession->IBuffer->AvailableData();
						ProtoType iProtoType = *((ProtoType*)pProtoData);

						//检测协议合法性
						/*
						if (!P_ProtocolManager->CheckProtocolLegal(iProtoType))
						{
							HawkFmtError("UnknownProtocol: %d", iProtoType);						
							OnSessionError(pSession);
							return false;
						}
						*/

						//响应连接的Ping协议
						if (iProtoType == SysProtocol::SYS_CLT_PING)
						{
							//回复Pong响应
							SysProtocol::Sys_SvrPong sProto((UInt32)HawkOSOperator::GetSysTime());
							if (!SendProtocol(pSession, &sProto))
								return false;
						}
						//传递给网关, 再发往后端服务器
						else
						{
							//给网关发协议消息
							SendGateMsg(pSession->Sid, pProtoData, iProtoSize);
						}
						
						//移动数据游标
						pSession->IBuffer->MoveNonius(iProtoSize);

						//调用性能监视器(只记协议数, 避免流量统计不准确)
						if (m_pGateway->GetProfiler())
							m_pGateway->GetProfiler()->RegRecvProto(iProtoType, 0);
					}
				}				

				//移除输入缓冲的前段空白
				pSession->IBuffer->RemoveBlank();	
			}
		}
		return true;
	}