示例#1
0
static int
tr_peerIoTryRead( tr_peerIo * io, size_t howmuch )
{
    int res = 0;

    if(( howmuch = tr_bandwidthClamp( &io->bandwidth, TR_DOWN, howmuch )))
    {
        int e;

        EVUTIL_SET_SOCKET_ERROR( 0 );
        res = evbuffer_read( io->inbuf, io->socket, (int)howmuch );
        e = EVUTIL_SOCKET_ERROR( );

        dbgmsg( io, "read %d from peer (%s)", res, (res==-1?strerror(e):"") );

        if( EVBUFFER_LENGTH( io->inbuf ) )
            canReadWrapper( io );

        if( ( res <= 0 ) && ( io->gotError ) && ( e != EAGAIN ) && ( e != EINTR ) && ( e != EINPROGRESS ) )
        {
            char errstr[512];
            short what = EVBUFFER_READ | EVBUFFER_ERROR;
            if( res == 0 )
                what |= EVBUFFER_EOF;
            tr_net_strerror( errstr, sizeof( errstr ), e );
            dbgmsg( io, "tr_peerIoTryRead got an error. res is %d, what is %hd, errno is %d (%s)", res, what, e, errstr );
            io->gotError( io, what, io->userData );
        }
    }

    return res;
}
示例#2
0
文件: ui.c 项目: cmdrclueless/honeyd
static void
ui_handler(evutil_socket_t fd, short what, void *arg)
{
	struct uiclient *client = arg;

	if (evbuffer_read(client->inbuf, fd, -1) <= 0) {
		ui_dead(client);
		return;
	}

	for (;;) {
		size_t eol_len;
		struct evbuffer_ptr line = evbuffer_search_eol(client->inbuf, NULL, &eol_len, EVBUFFER_EOL_LF);
		if (line.pos == -1)
			break;

		char *p = (char *)malloc(line.pos + 1);
		if (p != NULL) {
			evbuffer_remove(client->inbuf, (void *)p, line.pos);
			p[line.pos] = '\0'; /* ensure termination */

			evbuffer_drain(client->inbuf, eol_len);

			ui_handle_command(client->outbuf, p);
			free(p);
		}
	}

	ui_write_prompt(client);

	event_add(client->ev_read, NULL);
}
示例#3
0
void conn_input (int sockfd, short event, void* arg)
{
    g_print("%d :conn input %d\n", sockfd, event);

    connection_t *conn = NULL;

    if ( arg ){
        conn = (connection_t *)arg;
    }

    if ( EV_TIMEOUT == event )
    {
        printf("arg is %p, timeout\n", arg);
        event_add (&conn->ev_read, NULL);
    	timeout_add(&conn->ev_read, &conn->tv);
    }

    if ( EV_READ == event)
    {
        printf("arg is %p, read data\n", arg);
        event_add (&conn->ev_read, NULL);
    	timeout_add(&conn->ev_read, &conn->tv);
        evbuffer_read(conn->input, conn->sockfd, 256);
    }

}
示例#4
0
文件: httplib.c 项目: jzyuchen/Study
static void http_read_cb(evutil_socket_t fd, short events, void *arg)
{
	int ret = 0;
	struct http_connection *hc = arg;

	if (events & EV_TIMEOUT) {
		printf("timeout on fd %d, hc %p\n", fd, hc);
		goto failed;
	}

	if (events & EV_READ) {
		ret = evbuffer_read(hc->evbin, fd, 4096);
		if (ret == -1 || ret == 0) {
			goto failed;
		}

		if (hc->connection_status == HTTP_CONNECTION_STATUS_READ_HEADER) {
			if (evbuffer_find(hc->evbin, (const unsigned char *)"\r\n\r\n", 4) == NULL &&
				evbuffer_get_length(hc->evbin) < 4096)
			{
				// wait to read more data
				return;
			} else {
				//dbprintf("evbuffer_get_length: %d\n", evbuffer_get_length(hc->evbin));
			}

			ret = http_parse_first_line(hc, hc->evbin);
			if (ret) {
				goto failed;
			}

			ret = http_parse_headers(hc, hc->evbin);
			if (ret) {
				goto failed;
			}

			/* set no-timeout read */
			event_del(hc->ev_read);
			event_add(hc->ev_read, NULL);
			hc->connection_status = HTTP_CONNECTION_STATUS_READ_BODY;
		} else if (hc->connection_status == HTTP_CONNECTION_STATUS_READ_BODY) {

		}

		/* dispatch to handler */
		ret = http_dispatch_uri_handler_cb(hc);
		if (ret) {
			goto failed;
		}
	}

	return;
failed:
	http_connection_free(hc);
}
示例#5
0
文件: client.c 项目: dividuum/infon
static void client_readable(int fd, short event, void *arg) {
    int ret = evbuffer_read(in_buf, fd, 8192);
    if (ret < 0) {
        client_destroy(strerror(errno));
    } else if (ret == 0) {
        client_destroy("eof reached");
    } else {
        traffic += ret;
        client_parse_in_buf();
    }
}
示例#6
0
文件: evbuffer.c 项目: aosm/openmpi
static void
bufferevent_readcb(int fd, short event, void *arg)
{
	struct bufferevent *bufev = arg;
	int res = 0;
	short what = OPAL_EVBUFFER_READ;
	size_t len;

	if (event == OPAL_EV_TIMEOUT) {
		what |= OPAL_EVBUFFER_TIMEOUT;
		goto error;
	}

	res = evbuffer_read(bufev->input, fd, -1);
	if (res == -1) {
		if (errno == EAGAIN || errno == EINTR)
			goto reschedule;
		/* error case */
		what |= OPAL_EVBUFFER_ERROR;
	} else if (res == 0) {
		/* eof case */
		what |= OPAL_EVBUFFER_EOF;
	}

	if (res <= 0)
		goto error;

	bufferevent_add(&bufev->ev_read, bufev->timeout_read);

	/* See if this callbacks meets the water marks */
	len = OPAL_EVBUFFER_LENGTH(bufev->input);
	if (bufev->wm_read.low != 0 && len < bufev->wm_read.low)
		return;
	if (bufev->wm_read.high != 0 && len > bufev->wm_read.high) {
		struct evbuffer *buf = bufev->input;
		opal_event_del(&bufev->ev_read);

		/* Now schedule a callback for us */
		evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev);
		return;
	}

	/* Invoke the user callback - must always be called last */
	(*bufev->readcb)(bufev, bufev->cbarg);
	return;

 reschedule:
	bufferevent_add(&bufev->ev_read, bufev->timeout_read);
	return;

 error:
	(*bufev->errorcb)(bufev, what, bufev->cbarg);
}
示例#7
0
/** 
 * 窥探缓冲区,但不清空
 * 参考read函数
 * 如果@buf为空,则返回缓冲区长度
 */
int im_connection::peek(char* buf, int max_len)
{
	int buflen = evbuffer_get_length(_in);
	if (buflen < max_len) {
		if (evbuffer_read(_in, _fd, max_len-buflen) < 0) {
			if (_ops->network_disconnected)
				_ops->network_disconnected(this);
			return -1;
		}
	}

	if (buf)
		return evbuffer_copyout(_in, buf, max_len);
	else
		return evbuffer_get_length(_in);
}
示例#8
0
文件: server.c 项目: dividuum/infon
static void server_readable(int fd, short event, void *arg) {
    client_t *client = (client_t*)arg;

    // Der Client wurde 'extern' gekickt, allerdings noch
    // nicht entfernt. Dann wird dieser Readcallback aufgerufen,
    // sollte allerdings nichts mehr machen.
    if (client->kill_me)
        return;

    int ret = evbuffer_read(client->in_buf, fd, 128);
    if (ret < 0) {
        server_destroy(client, strerror(errno));
    } else if (ret == 0) {
        server_destroy(client, "eof reached");
    } else if (EVBUFFER_LENGTH(client->in_buf) > 8192) {
        server_destroy(client, "line too long. go away.");
    } else {
        char *line;
        while ((line = evbuffer_readline(client->in_buf))) {
            lua_pushliteral(L, "on_client_input");   
            lua_rawget(L, LUA_GLOBALSINDEX);      
            lua_pushnumber(L, client_num(client));
            lua_pushstring(L, line);
            free(line);

            // Cycles fuer die Verarbeitung hochsetzen
            lua_set_cycles(L, 0xFFFFFF);
                
            // Input verarbeiten
            output_client = client;
            if (lua_pcall(L, 2, 0, 0) != 0) {
                fprintf(stderr, "error calling on_client_input: %s\n", lua_tostring(L, -1));
                server_writeto(client, lua_tostring(L, -1), lua_strlen(L, -1));
                lua_pop(L, 1);
            }
            output_client = NULL;

            // Kill Me Flag waehrend Aufruf von on_client_input 
            // gesetzt? Direkt rausschmeissen!
            if (client->kill_me) {
                server_destroy(client, client->kill_me);
                return;
            }
        }
    }
}
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;
}
示例#10
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;
}
示例#11
0
void httpserver_handler(struct evhttp_request *req, void *arg)  
{  
    int fd=open("./test.html",O_RDONLY);
    const char *cmdtype;   
    struct evbuffer *buf = evbuffer_new();  
    if (buf == NULL)   
    {  
        printf("evbuffer_new error !\n");  
        return;  
    }  
      
    switch (evhttp_request_get_command(req))  
    {    
        case EVHTTP_REQ_GET:    cmdtype = "GET";    break;    
        case EVHTTP_REQ_POST:   cmdtype = "POST";   break;    
        case EVHTTP_REQ_HEAD:   cmdtype = "HEAD";   break;    
        case EVHTTP_REQ_PUT:    cmdtype = "PUT";    break;    
        case EVHTTP_REQ_DELETE: cmdtype = "DELETE"; break;    
        case EVHTTP_REQ_OPTIONS:cmdtype = "OPTIONS";break;    
        case EVHTTP_REQ_TRACE:  cmdtype = "TRACE";  break;    
        case EVHTTP_REQ_CONNECT:cmdtype = "CONNECT";break;    
        case EVHTTP_REQ_PATCH:  cmdtype = "PATCH";  break;    
        default: cmdtype = "unknown"; break;    
    }  
  
    printf("%s url=%s \n", cmdtype, evhttp_request_get_uri(req));  
  
    //evbuffer_add_printf(buf,"<html>\n"  
    //        "<head>\n"  
    //        "  <title>Libevnet Test</title>\n"            
    //        "</head>\n"  
    //        "<body>\n"  
    //        "  <h1>Hello world ,This is a Libenvet Test !</h1>\n"            
    //        "</body>\n"  
    //        "</html>\n");
    evbuffer_read(buf,fd,75);
    evhttp_send_reply(req, 200, "OK", buf);    
}   
示例#12
0
文件: echod.c 项目: trcm/COMP3301
void
echo_read(int fd, short revents, void *conn)
{
	int i;
// create buffer
/* struct evbuffer * eBuff = evbuffer_new(); */
// recieve and echo the message to the user
	char ** data;
	struct conn * c = (struct conn *) conn;
	data =  malloc(sizeof(char*) * 1024);
	for (i = 0; i < 1024; i++) {
		data[i] = malloc(sizeof(char) * 1024);
	}
	evbuffer_read(c->buf, fd, 1024);

/* evbuffer_read(c->buf, fd, 1024); */
	fprintf(stdout, "fd %d: %s\n", fd, (char *)c->buf->buffer);
/* fflush(stdout); */
	write(fd, "Message recieved\n", 18);
/* evbuffer_write(c->evbuffer, fd); */
// free the buffer
	event_add(&c->wr_ev, NULL);
}
示例#13
0
int sp_in_event(int fd, short why, void *data)
{
    sp_t *sp = data;

    int rc = evbuffer_read(sp->input, fd, 4096);
    if(rc == -1 || rc == 0 /* EOF */)
    {
        return -1;
    }

    while(1)
    {
        char *cmd = io_evbuffer_readline(sp->input);
        if(cmd == NULL)
        {
            break;
        }
        print_command(cmd, "<- (fd %d)", fd);
        sp_dispatch_command(cmd, "$", 1, sp);
        free(cmd);
    }

    return 0;
}
示例#14
0
void connection_client(int cfd, short event, void *arg)
{
    struct client_state *cs = arg;
    int cmd, break_out = 0;
    int uid = 0, index = 0;

    // ignore clients that timeout
    if (event & EV_TIMEOUT)
	cs->state = FSM_EXIT;

    if (event & EV_READ) {
	if (cs->state != FSM_ENTER) {
	    if (evbuffer_read(cs->evb, cfd, READ_BLOCK) <= 0)
		cs->state = FSM_EXIT;
	}
	else {
	    if (evbuffer_read(cs->evb, cfd, 4) <= 0)
		cs->state = FSM_EXIT;
	}
    }

    while (!break_out) {
	switch (cs->state) {
	    case FSM_ENTER:
		if (EVBUFFER_LENGTH(cs->evb) < sizeof(int)) {
		    break_out = 1;
		    break;
		}
		evbuffer_remove(cs->evb, &cmd, sizeof(cmd));
		if (cmd == -1)
		    cs->state = FSM_SYNC;
		else if (cmd == -2) {
		    fcntl(cfd, F_SETFL, fcntl(cfd, F_GETFL, 0) | O_NONBLOCK);
		    cs->state = FSM_LOGIN;
		}
		else if (cmd >= 0)
		    cs->state = FSM_EXIT;
		else {
		    printf("unknown cmd=%d\n",cmd);
		    cs->state = FSM_EXIT;
		}
		break;
	    case FSM_SYNC:
		syncutmp(cfd);
		firstsync = 1;
		cs->state = FSM_EXIT;
		break;
	    case FSM_LOGIN:
		if (firstsync) {
		    if (EVBUFFER_LENGTH(cs->evb) < (2 + MAX_FRIEND + MAX_REJECT) * sizeof(int)) {
			break_out = 1;
			break;
		    }
		    evbuffer_remove(cs->evb, &index, sizeof(index));
		    evbuffer_remove(cs->evb, &uid, sizeof(uid));
		    if (index >= USHM_SIZE || index < 0) {
			fprintf(stderr, "bad index=%d\n", index);
			cs->state = FSM_EXIT;
			break;
		    }
		    if (uid > MAX_USERS || uid <= 0) {
			fprintf(stderr, "bad uid=%d\n", uid);
			cs->state = FSM_EXIT;
			break;
		    }
		    count_login++;
		    processlogin(cs, uid, index);
		    if (count_login >= 4000 || (time(NULL) - begin_time) > 30*60)
			showstat();
		    cs->state = FSM_WRITEBACK;
		    break_out = 1;
		}
		else
		    cs->state = FSM_EXIT;
		break;
	    case FSM_WRITEBACK:
		if (event & EV_WRITE)
		    if (evbuffer_write(cs->evb, cfd) <= 0 && EVBUFFER_LENGTH(cs->evb) > 0)
			break_out = 1;
		if (EVBUFFER_LENGTH(cs->evb) == 0)
		    cs->state = FSM_EXIT;
		break;
	    case FSM_EXIT:
		if (clients == MAX_CLIENTS)
		    event_add(&ev, NULL);
		close(cfd);
		evbuffer_free(cs->evb);
		free(cs);
		clients--;
		return;
		break;
	}
    }
    if (cs->state == FSM_WRITEBACK)
	event_set(&cs->ev, cfd, EV_WRITE, (void *) connection_client, cs);
    event_add(&cs->ev, &tv);
}
示例#15
0
/* Thread: httpd */
static void
serve_file(struct evhttp_request *req, char *uri)
{
  const char *host;
  char *ext;
  char path[PATH_MAX];
  char *deref;
  char *ctype;
  char *passwd;
  struct evbuffer *evbuf;
  struct evkeyvalq *headers;
  struct stat sb;
  int fd;
  int i;
  int ret;

  /* Check authentication */
  passwd = cfg_getstr(cfg_getsec(cfg, "general"), "admin_password");
  if (passwd)
    {
      DPRINTF(E_DBG, L_HTTPD, "Checking web interface authentication\n");

      ret = httpd_basic_auth(req, "admin", passwd, PACKAGE " web interface");
      if (ret != 0)
	return;

      DPRINTF(E_DBG, L_HTTPD, "Authentication successful\n");
    }
  else
    {
      host = evhttp_request_get_host(req);
      if ((strcmp(host, "::1") != 0)
	  && (strcmp(host, "127.0.0.1") != 0))
	{
	  DPRINTF(E_LOG, L_HTTPD, "Remote web interface request denied; no password set\n");

	  evhttp_send_error(req, 403, "Forbidden");
	  return;
	}
    }

  ret = snprintf(path, sizeof(path), "%s%s", WEBFACE_ROOT, uri + 1); /* skip starting '/' */
  if ((ret < 0) || (ret >= sizeof(path)))
    {
      DPRINTF(E_LOG, L_HTTPD, "Request exceeds PATH_MAX: %s\n", uri);

      evhttp_send_error(req, HTTP_NOTFOUND, "Not Found");

      return;
    }

  ret = lstat(path, &sb);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_HTTPD, "Could not lstat() %s: %s\n", path, strerror(errno));

      evhttp_send_error(req, HTTP_NOTFOUND, "Not Found");

      return;
    }

  if (S_ISDIR(sb.st_mode))
    {
      redirect_to_index(req, uri);

      return;
    }
  else if (S_ISLNK(sb.st_mode))
    {
      deref = m_realpath(path);
      if (!deref)
	{
	  DPRINTF(E_LOG, L_HTTPD, "Could not dereference %s: %s\n", path, strerror(errno));

	  evhttp_send_error(req, HTTP_NOTFOUND, "Not Found");

	  return;
	}

      if (strlen(deref) + 1 > PATH_MAX)
	{
	  DPRINTF(E_LOG, L_HTTPD, "Dereferenced path exceeds PATH_MAX: %s\n", path);

	  evhttp_send_error(req, HTTP_NOTFOUND, "Not Found");

	  free(deref);
	  return;
	}

      strcpy(path, deref);
      free(deref);

      ret = stat(path, &sb);
      if (ret < 0)
	{
	  DPRINTF(E_LOG, L_HTTPD, "Could not stat() %s: %s\n", path, strerror(errno));

	  evhttp_send_error(req, HTTP_NOTFOUND, "Not Found");

	  return;
	}

      if (S_ISDIR(sb.st_mode))
	{
	  redirect_to_index(req, uri);

	  return;
	}
    }

  if (path_is_legal(path) != 0)
    {
      evhttp_send_error(req, 403, "Forbidden");

      return;
    }

  evbuf = evbuffer_new();
  if (!evbuf)
    {
      DPRINTF(E_LOG, L_HTTPD, "Could not create evbuffer\n");

      evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal error");
      return;
    }

  fd = open(path, O_RDONLY);
  if (fd < 0)
    {
      DPRINTF(E_LOG, L_HTTPD, "Could not open %s: %s\n", path, strerror(errno));

      evhttp_send_error(req, HTTP_NOTFOUND, "Not Found");
      return;
    }

  /* FIXME: this is broken, if we ever need to serve files here,
   * this must be fixed.
   */
  ret = evbuffer_read(evbuf, fd, sb.st_size);
  close(fd);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_HTTPD, "Could not read file into evbuffer\n");

      evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal error");
      return;
    }

  ctype = "application/octet-stream";
  ext = strrchr(path, '.');
  if (ext)
    {
      for (i = 0; ext2ctype[i].ext; i++)
	{
	  if (strcmp(ext, ext2ctype[i].ext) == 0)
	    {
	      ctype = ext2ctype[i].ctype;
	      break;
	    }
	}
    }

  headers = evhttp_request_get_output_headers(req);

  evhttp_add_header(headers, "Content-Type", ctype);
  evhttp_send_reply(req, HTTP_OK, "OK", evbuf);

  evbuffer_free(evbuf);
}
示例#16
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);
}
示例#17
0
文件: evbuffer.c 项目: wtyelec/code
/*
 * zark: 当epoll层的读事件到来, 会从活跃队列中回调该函数,
 *       开始从socket中读取数据.
 */
static void
bufferevent_readcb(int fd, short event, void *arg)
{
	struct bufferevent *bufev = arg;
	int res = 0;
	short what = EVBUFFER_READ;
	size_t len;
	int howmuch = -1;

    //! zark: bufferevent是对I/O操作的封装, 所以不监听超时事件.
	if (event == EV_TIMEOUT) {
		what |= EVBUFFER_TIMEOUT;
		goto error;
	}

	/*
	 * If we have a high watermark configured then we don't want to
	 * read more data than would make us reach the watermark.
     *
     * zark: 这里有必要普及一下libevent关于输入输出时的水位概念.
     *      读取低水位 - 读取操作使得输入缓冲区的数据量在此级别或者更高时,
     *                   读取回调将被调用.默认值为0, 所以每个读取操作都会
     *                   导致读取回调被调用.
     *      读取高水位 - 输入缓冲区中的数据量达到此级别后,bufferevent将停
     *                   止读取,直到输入缓冲区中足够量的数据被抽取,使得数
     *                   据量低于此级别.默认值是无限, 所以永远不会因为输入
     *                   缓冲区的大小而停止读取.
     *      写入低水位 - 写入操作使得输出缓冲区的数据量达到或者低于此级别时,
     *                   写入回调将被调用.默认值是0, 所以只有输出缓冲区空的
     *                   时候才会调用写入回调.
     *      写入高水位 - bufferevent没有直接使用这个水位. 它在bufferevent用
     *                   作另外一个bufferevent的底层传输端口时有特殊意义.请
     *                   看后面关于过滤型bufferevent的介绍.
	 */

    //! zark: 读取高水位到达, 停止读取.
	if (bufev->wm_read.high != 0) {
		howmuch = bufev->wm_read.high - EVBUFFER_LENGTH(bufev->input);
		/* we might have lowered the watermark, stop reading */
		if (howmuch <= 0) {
			struct evbuffer *buf = bufev->input;
			event_del(&bufev->ev_read); //! 删除当前读事件.
            /*
             * zark: 设置一个新的读事件, 该读事件的callback函
             *       数(即bufferevent_read_pressure_cb)会检测
             *       当输入冲区大小小于高水位时, 会再次添加正
             *       常的读取event.
             */
			evbuffer_setcb(buf,
			    bufferevent_read_pressure_cb, bufev);
			return;
		}
	}

    /*
     * zark: 开始从fd读取数据到我们的输入缓冲区中.
     */
	res = evbuffer_read(bufev->input, fd, howmuch);
	if (res == -1) {
		if (errno == EAGAIN || errno == EINTR)
			goto reschedule;
		/* error case */
		what |= EVBUFFER_ERROR;
	} else if (res == 0) {
		/* eof case */
		what |= EVBUFFER_EOF;
	}

	if (res <= 0)
		goto error;

    /*
     * zark: 因为bufferevent当初添加事件的时候没有使用
     *       persist来修饰event, 所以需要重新添加.
     */
	bufferevent_add(&bufev->ev_read, bufev->timeout_read);

	/* See if this callbacks meets the water marks */
	len = EVBUFFER_LENGTH(bufev->input);

    /*
     * zark: 读取低水位线没有达到, 所以不能调用callback, 直接return~
     */
	if (bufev->wm_read.low != 0 && len < bufev->wm_read.low)
		return;

    /*
     * zark: 读取高水位到达, 停止读取.
     */
	if (bufev->wm_read.high != 0 && len >= bufev->wm_read.high) {
		struct evbuffer *buf = bufev->input;
		event_del(&bufev->ev_read);

		/* Now schedule a callback for us when the buffer changes */
		evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev);
	}

	/* Invoke the user callback - must always be called last */
    /*
     * zark: 哈哈, 一顿乱七八糟的check下来, 终于到了调用我们
     *       真正注册的读取回调函数拉~ 散花~
     */
	if (bufev->readcb != NULL)
		(*bufev->readcb)(bufev, bufev->cbarg);
	return;

 reschedule:
	bufferevent_add(&bufev->ev_read, bufev->timeout_read);
	return;

    /*
     * zark: 调用我们注册的错误处理回调函数.
     */
 error:
	(*bufev->errorcb)(bufev, what, bufev->cbarg);
}
示例#18
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);
}
示例#19
0
static void
bufferevent_readcb(int fd, short event, void *arg)
{
	struct bufferevent *bufev = arg;
	int res = 0;
	short what = EVBUFFER_READ;
	size_t len;
	int howmuch = -1;

	if (event == EV_TIMEOUT) {
		what |= EVBUFFER_TIMEOUT;
		goto error;
	}

	/*
	 * 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_LENGTH(bufev->input);
		/* we might have lowered the watermark, stop reading */
		if (howmuch <= 0) {
			struct evbuffer *buf = bufev->input;
			event_del(&bufev->ev_read);
			evbuffer_setcb(buf,
			    bufferevent_read_pressure_cb, bufev);
			return;
		}
	}

	res = evbuffer_read(bufev->input, fd, howmuch);
	if (res == -1) {
		if (errno == EAGAIN || errno == EINTR)
			goto reschedule;
		/* error case */
		what |= EVBUFFER_ERROR;
	} else if (res == 0) {
		/* eof case */
		what |= EVBUFFER_EOF;
	}

	if (res <= 0)
		goto error;

	bufferevent_add(&bufev->ev_read, bufev->timeout_read);

	/* See if this callbacks meets the water marks */
	len = EVBUFFER_LENGTH(bufev->input);
	if (bufev->wm_read.low != 0 && len < bufev->wm_read.low)
		return;
	if (bufev->wm_read.high != 0 && len >= bufev->wm_read.high) {
		struct evbuffer *buf = bufev->input;
		event_del(&bufev->ev_read);

		/* Now schedule a callback for us when the buffer changes */
		evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev);
	}

	/* Invoke the user callback - must always be called last */
	if (bufev->readcb != NULL)
		(*bufev->readcb)(bufev, bufev->cbarg);
	return;

 reschedule:
	bufferevent_add(&bufev->ev_read, bufev->timeout_read);
	return;

 error:
	(*bufev->errorcb)(bufev, what, bufev->cbarg);
}
void shard_connection::handle_event(short evtype)
{
    // connect() returning to us?  normally we expect EV_WRITE, but for UNIX domain
    // sockets we workaround since connect() returned immediately, but we don't want
    // to do any I/O from the client::connect() call...
    if (!m_connected && (evtype == EV_WRITE || m_unix_sockaddr != NULL)) {
        int error = -1;
        socklen_t errsz = sizeof(error);

        if (getsockopt(m_sockfd, SOL_SOCKET, SO_ERROR, (void *) &error, &errsz) == -1) {
            benchmark_error_log("connect: error getting connect response (getsockopt): %s\n", strerror(errno));
            return;
        }

        if (error != 0) {
            benchmark_error_log("connect: connection failed: %s\n", strerror(error));
            return;
        }

        m_connected = true;
        if (!m_conns_manager->get_reqs_processed()) {
            process_first_request();
        } else {
            benchmark_debug_log("reconnection complete, proceeding with test\n");
            fill_pipeline();
        }
    }

    assert(m_connected == true);
    if ((evtype & EV_WRITE) == EV_WRITE && evbuffer_get_length(m_write_buf) > 0) {
        if (evbuffer_write(m_write_buf, m_sockfd) < 0) {
            if (errno != EWOULDBLOCK) {
                benchmark_error_log("write error: %s\n", strerror(errno));
                disconnect();

                return;
            }
        }
    }

    if ((evtype & EV_READ) == EV_READ) {
        int ret = 1;
        while (ret > 0) {
            ret = evbuffer_read(m_read_buf, m_sockfd, -1);
        }

        if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
            benchmark_error_log("read error: %s\n", strerror(errno));
            disconnect();

            return;
        }
        if (ret == 0) {
            benchmark_error_log("connection dropped.\n");
            disconnect();

            return;
        }

        if (evbuffer_get_length(m_read_buf) > 0) {
            process_response();

            // process_response may have disconnected, in which case
            // we just abort and wait for libevent to call us back sometime
            if (!m_connected) {
                return;
            }

        }
    }

    // update event
    short new_evtype = 0;
    if (m_pending_resp) {
        new_evtype = EV_READ;
    }

    if (evbuffer_get_length(m_write_buf) > 0) {
        assert(!m_conns_manager->finished());
        new_evtype |= EV_WRITE;
    }

    if (new_evtype) {
        int ret = event_assign(m_event, m_event_base,
                               m_sockfd, new_evtype, cluster_client_event_handler, (void *)this);
        assert(ret == 0);

        ret = event_add(m_event, NULL);
        assert(ret == 0);
    } else if (m_conns_manager->finished()) {
        m_conns_manager->set_end_time();
    }
}
示例#21
0
static void
event_read_cb( int fd, short event UNUSED, void * vio )
{
    int res;
    int e;
    tr_peerIo * io = vio;

    /* Limit the input buffer to 256K, so it doesn't grow too large */
    unsigned int howmuch;
    unsigned int curlen;
    const tr_direction dir = TR_DOWN;
    const unsigned int max = 256 * 1024;

    assert( tr_isPeerIo( io ) );

    io->hasFinishedConnecting = TRUE;
    io->pendingEvents &= ~EV_READ;

    curlen = EVBUFFER_LENGTH( io->inbuf );
    howmuch = curlen >= max ? 0 : max - curlen;
    howmuch = tr_bandwidthClamp( &io->bandwidth, TR_DOWN, howmuch );

    dbgmsg( io, "libevent says this peer is ready to read" );

    /* if we don't have any bandwidth left, stop reading */
    if( howmuch < 1 ) {
        tr_peerIoSetEnabled( io, dir, FALSE );
        return;
    }

    EVUTIL_SET_SOCKET_ERROR( 0 );
    res = evbuffer_read( io->inbuf, fd, (int)howmuch );
    e = EVUTIL_SOCKET_ERROR( );

    if( res > 0 )
    {
        tr_peerIoSetEnabled( io, dir, TRUE );

        /* Invoke the user callback - must always be called last */
        canReadWrapper( io );
    }
    else
    {
        char errstr[512];
        short what = EVBUFFER_READ;

        if( res == 0 ) /* EOF */
            what |= EVBUFFER_EOF;
        else if( res == -1 ) {
            if( e == EAGAIN || e == EINTR ) {
                tr_peerIoSetEnabled( io, dir, TRUE );
                return;
            }
            what |= EVBUFFER_ERROR;
        }

        tr_net_strerror( errstr, sizeof( errstr ), e );
        dbgmsg( io, "event_read_cb got an error. res is %d, what is %hd, errno is %d (%s)", res, what, e, errstr );

        if( io->gotError != NULL )
            io->gotError( io, what, io->userData );
    }
}
示例#22
0
static void
echo_read_cb(struct bufferevent *bev, void *ctx)
{
    printf("echo_read_cb ctx:%p\n", ctx);
    /* This callback is invoked when there is data to read on bev. */
    struct evbuffer *input = bufferevent_get_input(bev);

    /* Copy all the data from the input buffer to the output buffer. */
    // evbuffer_add_buffer(output, input);
    // 能读到数据的时候 去连接其他server 而且是以阻塞的方式

    printf("echo_read_cb1 \n");
    struct sockaddr_in servaddr;
    memset(&servaddr, 0, sizeof(servaddr));
    //servaddr.sin_family = AF_INET;
    ////servaddr.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */
    //if (inet_aton("192.168.1.104", &servaddr.sin_addr) == 0)
    //{
    //	perror("inet_aton failure!");
    //	printf("address:%u\n", servaddr.sin_addr.s_addr);
    //	exit(EXIT_FAILURE);
    //}

    //servaddr.sin_port = htons(5188); /* Port 9876*/

    // TODO 错误判断
    char buff[64];
    evutil_snprintf(buff, sizeof(buff), "%s:%d", "192.168.1.104", 5188);
    int servadd_len = sizeof(servaddr);
    //int retx = evutil_parse_sockaddr_port("192.168.1.104:5188", (struct sockaddr*)&servaddr, &servadd_len);
    int retx = evutil_parse_sockaddr_port(buff, (struct sockaddr*)&servaddr, &servadd_len);

    printf("address:%s\n", buff);
    if (retx < 0)
    {
        printf("address:error\n");
    }
    else
    {
        printf("address:%u\n", servaddr.sin_addr.s_addr);
    }
    int sockconn;
    errno = 0;
    if ((sockconn = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
    {
        perror("socket failure");
        exit(EXIT_FAILURE);
    }
    //evutil_make_socket_nonblocking(sockconn);

    struct timeval	tv;
    tv.tv_sec = 5;
    tv.tv_usec = 0;
    setsockopt(sockconn, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
    setsockopt(sockconn, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
    // bufferevent_socket_new 只是分配内存 没有系统调用
    struct bufferevent *bev1 = bufferevent_socket_new(ctx, sockconn, BEV_OPT_CLOSE_ON_FREE);
    //bufferevent_settimeout(bev1, 10, 10);
    //bev1 = bufferevent_socket_new(ctx, -1, BEV_OPT_CLOSE_ON_FREE);
    bufferevent_enable(bev1, EV_READ|EV_WRITE);
    bufferevent_setcb(bev1, NULL, NULL, eventcb, "hello");
    //SetSocketBlockingEnabled(sockconn, 1);

    // 这里默认是阻塞的,会一直阻塞 直到连接成功 或超时 // //
    if (bufferevent_socket_connect(bev1,
                                   (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
        /* Error starting connection */
        // 连接不能马上建立的时候 应该添加到写事件中
        fprintf(stderr, "Connect failed.\n");
        perror("connect...........");
        //#define	ETIMEDOUT	110	/* Connection timed out */
        // 无条件超时 非自定义超时  走这里//
        //bufferevent_free(bev1);
        // 此时错误码是 BEV_EVENT_ERROR 在那里销毁 BEV_EVENT_ERROR
        //return -1;
        // 110错误码走到这里  11, 115错误码 不会走到这里
    }
    printf("bufferevent_socket_connect return errno:%d \n", errno);
    ////#define	EAGAIN		11	/* Try again */
    ////#define	ECONNREFUSED	111	/* Connection refused */
    ////#define	EINPROGRESS	115	/* Operation now in progress */ // connect 被超时打断11,


    //
    //if (errno != EAGAIN )
    if (errno == EINPROGRESS) // 自定义 超时中断
    {
        perror("self timeout.............");
        bufferevent_free(bev1);
        return;
    }
    else if (errno != 0)
    {
        perror("00buffevent_connect");
        printf("bufferevent_socket_connect error\n");
        //如果 在过程中 超时会被 打断	EINPROGRESS	115	/* Operation now in progress */

        // 除了自定义超时timeout不宜在这里销毁 在 回调函数中销毁 不然调用不到回调函数//

        //bufferevent_free(bev1);
        return ;
    }
    else
    {
        // 连接成功
        perror("11buffevent_connect");
        printf("bufferevent_socket_connect success\n");
    }


    //if (connect(sockconn, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
    //{
    //	perror("connnect error");
    //	exit(EXIT_FAILURE);
    //}
    //else
    //{
    //	printf("connect success\n");
    //}

    //char recvbuf[1024] = {0};
    //memset(recvbuf, 0, sizeof(recvbuf));
    //sleep(5);
    //read(sockconn, recvbuf, sizeof(recvbuf));
    //printf("----%s-----\n", recvbuf);

//	struct evbuffer *input1 = bufferevent_get_input(bev1);
//	printf("before read ---------\n");
//	bufferevent_read_buffer(bev1, input1);
//	size_t len =  evbuffer_get_length(input1);
//	unsigned char * recvbuf = evbuffer_pullup(input1, len);
//	printf("end read len:%ld---------\n", len);
//	printf("----%s-----\n", recvbuf);


    //struct evbuffer * buffer =  evbuffer_new();
    struct evbuffer *buffer = bufferevent_get_input(bev1);
    struct evbuffer *buffero = bufferevent_get_output(bev1);
    evutil_socket_t fd =  bufferevent_getfd(bev1);

    time_t rawtime;
    time ( &rawtime );
    printf("before read ---------%ld\n", rawtime);
    int  ret = evbuffer_read(buffer, fd, 1024);
    // not work
    // bufferevent_read_buffer(bev1, buffer);
    size_t len =  evbuffer_get_length(buffer);
    time ( &rawtime );
    printf("end readlen  ---------%ld\n", len);
    unsigned char * recvbuf = evbuffer_pullup(buffer, len);
    printf("end read    ---------%ld\n", rawtime);
    printf("----%s-----\n", recvbuf);
    evbuffer_drain(buffer, len);
    // int evbuffer_write(struct evbuffer *buffer, evutil_socket_t fd);
    time ( &rawtime );
    printf("before write---------%ld\n", rawtime);
    sleep(10);
    time ( &rawtime );
    printf("before write1---------%ld\n", rawtime);
    evbuffer_add(buffero, "hello,china", 12);
    ret = evbuffer_write(buffero, fd);
    // ret =write(fd, "hello,china", 12);
    if (ret < 0)
    {
        if (errno != 0)
        {
            perror("write ");
        }
    }

    time ( &rawtime );
    printf("end write1   ---------%ld\n", rawtime);

    // 出现read 在connect 之前//
    //root@debian:~/programming/libevent/libevent2/libevent/sample/study-buffevent_block# ./echoserver_block
    //	create listener success, base:0xfdbc40
    //	echo_read_cb ctx:0xfdbc40
    //	echo_read_cb1
    //	bufferevent_socket_connect return errno:11
    //	11buffevent_connect: Resource temporarily unavailable
    //	bufferevent_socket_connect success
    //	----hello,world-----
    //	Connect okay,-------------------------- hello.
    //	disConnect --------------------------.

}
示例#23
0
static void
bufferevent_readcb(int fd, short event, void *arg)
{
	struct bufferevent *bufev = arg;
	int res = 0;
	short what = EVBUFFER_READ;
	size_t len;
	int howmuch = -1;

	if (event == EV_TIMEOUT) {
		what |= EVBUFFER_TIMEOUT;
		goto error;
	}

	if (bufev->wm_read.high != 0) {
		howmuch = bufev->wm_read.high - EVBUFFER_LENGTH(bufev->input);
		
		if (howmuch <= 0) {
			struct evbuffer *buf = bufev->input;
			event_del(&bufev->ev_read);
			evbuffer_setcb(buf,
			    bufferevent_read_pressure_cb, bufev);
			return;
		}
	}

	res = evbuffer_read(bufev->input, fd, howmuch);
	if (res == -1) {
		if (errno == EAGAIN || errno == EINTR)
			goto reschedule;
		
		what |= EVBUFFER_ERROR;
	} else if (res == 0) {
		
		what |= EVBUFFER_EOF;
	}

	if (res <= 0)
		goto error;

	bufferevent_add(&bufev->ev_read, bufev->timeout_read);

	
	len = EVBUFFER_LENGTH(bufev->input);
	if (bufev->wm_read.low != 0 && len < bufev->wm_read.low)
		return;
	if (bufev->wm_read.high != 0 && len >= bufev->wm_read.high) {
		struct evbuffer *buf = bufev->input;
		event_del(&bufev->ev_read);

		
		evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev);
	}

	
	if (bufev->readcb != NULL)
		(*bufev->readcb)(bufev, bufev->cbarg);
	return;

 reschedule:
	bufferevent_add(&bufev->ev_read, bufev->timeout_read);
	return;

 error:
	(*bufev->errorcb)(bufev, what, bufev->cbarg);
}
示例#24
0
文件: mhf.c 项目: hehbhehb/mhf
/*
 * Reads data from a file descriptor into conn->input_buffer, parse and place the headers into conn->input_headers
 */
int mhf_read_buffer(CONN *conn)
{
	int n, len,ret;
	enum parse_result res;
	struct evbuffer *input_buffer = conn->input_buffer;
	int fd = conn->fd;
	conn->state = HTTP_STATE_READING_FIRSTLINE;
	while(1)
	{
		ret = mhf_select(fd, HTTP_TIMEOUT);	
		if (ret < 0) {
			fprintf(stderr,"%s %d %s select error \n",__func__,errno,strerror(errno));			
			return(-2);
		}
		else if (ret == 0) {
			fprintf(stderr,"%s timeout \n",__func__);	
			return(-1);
		}
		n = evbuffer_read(input_buffer, fd, -1);		
		if (n == -1) {
			if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
			{
				fprintf(stderr,"%s %d(EINTR||EAGAIN|EWOULDBLOCK) %s\n",__func__,errno,strerror(errno));
				continue;
			}
			else {
				fprintf(stderr,"%s %d(other error) %s\n",__func__,errno,strerror(errno));
				return(-2);
			}
		} 
		else if (n == 0) {
#ifdef DEBUG		
			fprintf(stderr,"%s connection closed \n",__func__);								
#endif
			return(-3); 		
		}

		while(1) {
			switch (conn->state) {
			case HTTP_STATE_READING_FIRSTLINE:
				res = mhf_read_firstline(conn);
				break;
			case HTTP_STATE_READING_HEADERS:
				res = mhf_read_header(conn);
				break;
			case HTTP_STATE_READING_BODY:
				break;
			case HTTP_STATE_END:
				return (0);				
			case HTTP_STATE_END_WITH_ERR:
#ifdef DEBUG				
				fprintf(stderr,"%s %d HTTP protocol error \n",__func__,res);
#endif
				return(-1);
			default:
				fprintf(stderr,"unsupported http state\n",__func__,res);
				exit(1);
			}
			if (res == MORE_DATA_EXPECTED)
				break;
		}
	}	
}