Exemplo n.º 1
0
void Worker::run()
{
    int ret;
    __dlist_t head;
    __dlist_t *next;
    Connection *conn;
    NOTICE("worker is running now.");
    while (!_stopped)
    {
        DLIST_INIT(&head);
        pthread_mutex_lock(&_mutex);
        while (DLIST_EMPTY(&_queue))
            pthread_cond_wait(&_cond, &_mutex);
        next = DLIST_NEXT(&_queue);
        DLIST_REMOVE(&_queue);
        pthread_mutex_unlock(&_mutex);
        DLIST_INSERT_B(&head, next);
        while (!DLIST_EMPTY(&head))
        {
            next = DLIST_NEXT(&head);
            DLIST_REMOVE(next);
            conn = GET_OWNER(next, Connection, _list);
            TRACE("start to process conn, sock[%d].", conn->_sock_fd);
            try
            {
                ret = conn->on_process();
                if (ret == 0)
                {
                    conn->_status = Connection::ST_PROCESSING_REQUEST_OK;
                    TRACE("process conn ok, sock[%d].", conn->_sock_fd);
                }
                else
                {
                    conn->_status = Connection::ST_PROCESSING_REQUEST_FAIL;
                    WARNING("failed to process conn, sock[%d], ret=%d.", conn->_sock_fd, ret);
                }
            }
            catch (...)
            {
                WARNING("failed to process conn, sock[%d], exception catched.", conn->_sock_fd);
            }
            _server_manager->done(conn);
        }
    }
    NOTICE("worker is stopped by user, exiting now.");
}
Exemplo n.º 2
0
int do_with_read_chunk_body(struct worker_context *ctx, struct connection *conn, int closed)
{
	if ( parse_chunk_body(ctx, conn) < 0 )
	{
		WARNING("failed to parse chunk body.");
		return -1;
	}
	else if (  REQUEST_CHUNK_BODY_STATE_END == conn->_client._state )
	{
		DEBUG("going to write to server.");
		struct body_buffer *buffer = GET_OWNER(conn->_client._cur_block, struct body_buffer, _list);
		conn->_client._next_len = buffer->_curpos - conn->_client._cur_pos;
		conn->_status = CONN_CONNECTING_SERVER;

		int curpos = 0;
		int ret;

		static const char *const s_version[] = 
		{
			"",
			"HTTP/0.9",
			"HTTP/1.0",
			"HTTP/1.1",
		};
		ret = snprintf(ctx->_header, MAX_HTTP_HEADER_LEN, "POST %.*s %s\r\n",
				(int)(conn->_client._uri_end - conn->_client._uri_start),
				conn->_client._uri_start, s_version[conn->_client._version]);
		if ( ret < 0 )
		{
			WARNING("snprintf error[%s].", strerror_t(errno));
			return -1;
		}
		curpos += ret;

		__dlist_t *cur;
		struct http_header *header;
		for ( cur = DLIST_NEXT(&conn->_client._headers); cur != &conn->_client._headers; cur = DLIST_NEXT(cur) )
		{
			header = GET_OWNER(cur, struct http_header, _list);
			if ( header->_name_end - header->_name_start == sizeof("Transfer-Encoding") - 1
					&& strncasecmp(header->_name_start, "Transfer-Encoding", sizeof("Transfer-Encoding") - 1) == 0 )
			{
				DEBUG("ignore Transfer-Encoding header.");
				continue;
			}
			else if ( header->_name_end - header->_name_start == sizeof("Content-Length") - 1
					&& strncasecmp(header->_name_start, "Content-Length", sizeof("Content-Length") - 1) == 0 )
			{
				DEBUG("ignore Content-Length header.");
				continue;
			}
			ret = snprintf(ctx->_header + curpos, MAX_HTTP_HEADER_LEN - curpos, "%.*s:%.*s\r\n",
					(int)(header->_name_end - header->_name_start), header->_name_start,
					(int)(header->_value_end - header->_value_start), header->_value_start);
			if ( ret < 0 )
			{
				WARNING("snprintf error[%s].", strerror_t(errno));
				return -1;
			}
			curpos += ret;
		}
		ret = snprintf(ctx->_header + curpos, MAX_HTTP_HEADER_LEN - curpos, "Content-Length:%d\r\n\r\n", conn->_client._body_len);
		if ( ret < 0 )
		{
			WARNING("snprintf error[%s].", strerror_t(errno));
			return -1;
		}
		if ( ret >= MAX_HTTP_HEADER_LEN - curpos )
		{
			WARNING("too long header, need[%s].", ret + curpos + 1);
			return -1;
		}
		curpos += ret;
		memcpy(conn->_client._header, ctx->_header, curpos);
		conn->_client._header_len = curpos;
		DEBUG("%s", ctx->_header);
	}
Exemplo n.º 3
0
void NetProxy::run()
{
#define SET_ERROR(errno)                                   \
    do                                                     \
    {                                                      \
        st->_errno = errno;                                \
        epex_detach(_epex, st->_talk->_sock, NULL);        \
    } while(0)

    ssize_t ret;
    netresult_t results[20];
    __dlist_t attach_ok_list;
    __dlist_t attach_fail_list;
    __dlist_t *ptr;
    NetStub *st;
    int sock;
    int tm_left;
    int elasp_tm;
    struct timeval now;

    _stop = false;
    while (!_stop)
    {
        DLIST_INIT(&attach_ok_list);
        DLIST_INIT(&attach_fail_list);
        {
            AutoLock __lock(_mutex);
            while (!DLIST_EMPTY(&_attach_list))
            {
                ptr = DLIST_NEXT(&_attach_list);
                st = GET_OWNER(ptr, NetStub, _att_list);
                DLIST_REMOVE(ptr);
                if (epex_attach(_epex, st->_talk->_sock, st, -1))
                    DLIST_INSERT_B(&st->_tmp_list, &attach_ok_list);
                else
                    DLIST_INSERT_B(&st->_tmp_list, &attach_fail_list);
            }
        }
        gettimeofday(&now, NULL);
        while (!DLIST_EMPTY(&attach_fail_list))
        {
            ptr = DLIST_NEXT(&attach_fail_list);
            st = GET_OWNER(ptr, NetStub, _tmp_list);
            DLIST_REMOVE(ptr);
            st->_errno = NET_ERR_ATTACH_FAIL;
            this->done(st, &now);
        }
        while (!DLIST_EMPTY(&attach_ok_list))
        {
            ptr = DLIST_NEXT(&attach_ok_list);
            st = GET_OWNER(ptr, NetStub, _tmp_list);
            DLIST_REMOVE(ptr);
            st->_talk->_req_head._magic_num = MAGIC_NUM;
            st->_talk->_req_head._body_len = st->_talk->_req_len;
            st->_status = NET_ST_SEND_HEAD;
            if (epex_write(_epex, st->_talk->_sock, &st->_talk->_req_head,
                        sizeof(st->_talk->_req_head), NULL, st->_timeout))
            {
                TRACE("try to send head to sock[%d]", st->_talk->_sock);
            }
            else
            {
                SET_ERROR(NET_ERR_WRITE);
            }
        }
        ret = epex_poll(_epex, results, sizeof(results)/sizeof(results[0]));
        gettimeofday(&now, NULL);
        for (long i = 0; i < ret; ++i)
        {
            const netresult_t &res = results[i];
            st = (NetStub *)res._user_ptr2;
            if (NET_OP_NOTIFY == res._op_type)
            {
                this->done(st, &now);
                continue;
            }
            switch (res._status)
            {
                case NET_DONE:
                    break;
                case NET_ECLOSED:
                    SET_ERROR(NET_ERR_CLOSED);
                    continue;
                case NET_ETIMEOUT:
                    SET_ERROR(NET_ERR_TIMEOUT);
                    continue;
                case NET_ERROR:
                    st->_errno = res._errno;
                    /* fall through */
                case NET_EDETACHED:
                    continue;
                default:
                    WARNING("should not be here, res._status=%hd", res._status);
                    continue;
            }
            sock = st->_talk->_sock;
            if (st->_cancel) /* canceled by user */
            {
                TRACE("sock[%d] is canceled by user", sock);
                epex_detach(_epex, sock, NULL);
                continue;
            }
            elasp_tm = (now.tv_sec - st->_start_tm.tv_sec) * 1000
                + (now.tv_usec - st->_start_tm.tv_usec) / 1000;
            if (st->_timeout < 0)
                tm_left = -1;
            else if (st->_timeout > elasp_tm)
                tm_left = st->_timeout - elasp_tm;
            else
                tm_left = 0;
            switch (st->_status)
            {
                case NET_ST_SEND_HEAD:
                    TRACE("send head to sock[%d] ok", sock);
                    st->_tm._send_head = elasp_tm;
                    st->_status = NET_ST_SEND_BODY;
                    if (tm_left == 0)
                    {
                        SET_ERROR(NET_ERR_TIMEOUT);
                        continue;
                    }
                    if (!epex_write(_epex, sock, st->_talk->_req_buf, st->_talk->_req_len,
                                NULL, tm_left))
                    {
                        SET_ERROR(NET_ERR_WRITE);
                        continue;
                    }
                    TRACE("try to send body[%u] to sock[%d]", st->_talk->_req_len, sock);
                    break;
                case NET_ST_SEND_BODY:
                    TRACE("send body[%u] to sock[%d] ok", st->_talk->_req_len, sock);
                    st->_tm._send_body = elasp_tm - st->_tm._send_head;
                    st->_status = NET_ST_RECV_HEAD;
                    if (tm_left == 0)
                    {
                        SET_ERROR(NET_ERR_TIMEOUT);
                        continue;
                    }
                    if (!epex_read(_epex, sock, &st->_talk->_res_head, sizeof(st->_talk->_res_head),
                                NULL, tm_left))
                    {
                        SET_ERROR(NET_ERR_READ);
                        continue;
                    }
                    TRACE("try to recv head from sock[%d]", sock);
                    break;
                case NET_ST_RECV_HEAD:
                    TRACE("recv head from sock[%d] ok", sock);
                    st->_tm._recv_head = elasp_tm - st->_tm._send_body - st->_tm._send_head;
                    if (st->_talk->_res_head._magic_num != MAGIC_NUM)
                    {
                        SET_ERROR(NET_ERR_MAGIC_NUM);
                        continue;
                    }
                    if (st->_talk->_res_head._body_len > st->_talk->_res_len)
                    {
                        SET_ERROR(NET_ERR_BIG_RESP);
                        continue;
                    }
                    st->_status = NET_ST_RECV_BODY;
                    if (tm_left == 0)
                    {
                        SET_ERROR(NET_ERR_TIMEOUT);
                        continue;
                    }
                    if (!epex_read(_epex, sock, st->_talk->_res_buf, st->_talk->_res_head._body_len,
                                NULL, tm_left))
                    {
                        SET_ERROR(NET_ERR_READ);
                        continue;
                    }
                    TRACE("try to recv body[%u] from sock[%d]", st->_talk->_res_head._body_len, sock);
                    break;
                case NET_ST_RECV_BODY:
                    TRACE("recv body[%u] from sock[%d] ok", st->_talk->_res_head._body_len, sock);
                    st->_tm._recv_body = elasp_tm - st->_tm._recv_head
                        - st->_tm._send_body - st->_tm._send_head;
                    st->_status = NET_ST_DONE;
                    epex_detach(_epex, sock, NULL);
                    TRACE("talk with sock[%d] ok", sock);
                    break;
                default:
                    WARNING("should not be here");
                    break;
            }
        }
    }
    NOTICE("NetPoller is stoped now");
#undef SET_ERROR
}
Exemplo n.º 4
0
int
main(int argc, char *argv[])
{
  myelmt_t *newelmt;
  myelmt_t *elmt;
  myctx_t *ctx;
  int i;
  int action;
  int j;
  int r;

  ctx = malloc(sizeof (myctx_t));

  DLIST_INIT(ctx, headlist);
  DLIST_INIT(ctx, taillist);

  for ( i = 0; i < 50000000 ; i++) {
    action = rand_range(0, 9);
    printf("action: %i\n", action);
    switch (action) {
    case ACTION_INSHEAD:
      elmt = malloc(sizeof (myelmt_t));
      elmt->blah = i;
      DLIST_INS_HEAD(ctx, headlist, elmt);
      break;

    case ACTION_INSTAIL:
      elmt = malloc(sizeof (myelmt_t));
      elmt->blah = i;
      DLIST_INS_TAIL(ctx, headlist, elmt);
      break;

    case ACTION_INSNEXT:
      printf("* insert after a random element.\n");
      newelmt = malloc(sizeof (myelmt_t));
      newelmt->blah = i;
      if (DLIST_IS_EMPTY(ctx, headlist)) {
        printf("    list is empty\n");
        DLIST_INS_HEAD(ctx, headlist, newelmt);
        continue ;
      }
      r = rand_range(0, DLIST_COUNT(ctx, headlist));
      for (j = 0, elmt = DLIST_HEAD(ctx, headlist) ;
           j < r;
           j++, elmt = DLIST_NEXT(headlist, elmt))
        ;
      DLIST_INS_NEXT(ctx, headlist, elmt, newelmt);
      break;

    case ACTION_INSPREV:
      printf("* insert before a random element.\n");
      newelmt = malloc(sizeof (myelmt_t));
      newelmt->blah = i;
      if (DLIST_IS_EMPTY(ctx, headlist)) {
        printf("    list is empty\n");
        DLIST_INS_HEAD(ctx, headlist, newelmt);
        continue ;
      }
      r = rand_range(0, DLIST_COUNT(ctx, headlist));
      for (j = 0, elmt = DLIST_HEAD(ctx, headlist) ;
           j < r;
           j++, elmt = DLIST_NEXT(headlist, elmt))
        ;
      DLIST_INS_PREV(ctx, headlist, elmt, newelmt);
      break;

    case ACTION_UNLINK1:
    case ACTION_UNLINK2:
    case ACTION_UNLINK3:
    case ACTION_UNLINK4:
    case ACTION_UNLINK5:
      printf("* unlink a random element.\n");
      if (DLIST_IS_EMPTY(ctx, headlist)) {
        printf("    list is empty\n");
        continue ;
      }
      r = rand_range(0, DLIST_COUNT(ctx, headlist));
      for (j = 0, elmt = DLIST_HEAD(ctx, headlist) ;
           j < r;
           j++, elmt = DLIST_NEXT(headlist, elmt))
        ;
      DLIST_UNLINK(ctx, headlist, elmt);
      free(elmt);
      break;

    case ACTION_SHOWLIST:
      printf("* show list content: (%i elements)\n", DLIST_COUNT(ctx, headlist));
      if ( DLIST_IS_EMPTY(ctx, headlist) ) {
        printf("    list is empty\n");
      } else {
        j = 0;
        DLIST_FOR_EACH(elmt, ctx, headlist) {
          printf("  elmt %i: val: %i\n", j, elmt->blah);
          j++;
        }
      }
      break;
    }
  }