Пример #1
0
void kismet_conn_eventcb(struct bufferevent *bev, short event, void* args) {
  DEBUG(255, "kismet_conn_eventcb(%p, 0x%02x, %p);", bev, event, args);
  if (!(event & BEV_EVENT_CONNECTED)) {
    struct event_base* base = bufferevent_get_base(bev);
    struct server* node = (struct server*) args;
    bufferevent_free(node->conn);
    node->conn = NULL;
    struct timeval tv = {node->timeout, 0};
    struct reconnect_struct* reconnect_struct = malloc(sizeof(struct reconnect_struct));
    reconnect_struct->server = node;
    reconnect_struct->base = base;
    struct inserter* inserter = node->inserters;
    while (inserter) {
      if (inserter->capabilities) {
        unsigned int next_token = 0;
        while (inserter->capabilities[next_token])
          free(inserter->capabilities[next_token++]);
        free(inserter->capabilities);
        inserter->capabilities = NULL;
      }
      inserter = inserter->next;
    };
    event_base_once(base, -1, EV_TIMEOUT, reconnectServer, reconnect_struct, &tv);
  }
};
Пример #2
0
/*
 * Handle socket events.
 */
static void v4c_srv_event(struct bufferevent *bev, short what, void *ctx)
{
    struct event_base *base = bufferevent_get_base(bev);
    unused(ctx);

    /* Handle only one client. */
    assert(bev == client);

    if (what & BEV_EVENT_READING) {
        ERR("Error while reading.");
    }
    if (what & BEV_EVENT_WRITING) {
        ERR("Error while writing.");
    }
    if (what & BEV_EVENT_EOF) {
        ERR("EOF reached.");
    }
    if (what & BEV_EVENT_ERROR) {
        ERR("Unrecoverable error encountered.");
    }
    if (what & BEV_EVENT_TIMEOUT) {
        ERR("Specified timout reached.");
    }
    if (what & BEV_EVENT_CONNECTED) {
        ERR("Connect operation done.");
    }
    if (what & (BEV_EVENT_EOF | BEV_EVENT_ERROR)) {
        bufferevent_free(bev);
        client = NULL;
        event_base_loopexit(base, NULL);
    }
}
Пример #3
0
/* Called periodically to check up on how full the buckets are */
static void
check_bucket_levels_cb(evutil_socket_t fd, short events, void *arg)
{
	struct bufferevent *bev = arg;

	ev_ssize_t r = bufferevent_get_read_limit(bev);
	ev_ssize_t w = bufferevent_get_write_limit(bev);
	ev_ssize_t rm = bufferevent_get_max_to_read(bev);
	ev_ssize_t wm = bufferevent_get_max_to_write(bev);
	/* XXXX check that no value is above the cofigured burst
	 * limit */
	total_rbucket_level += r;
	total_wbucket_level += w;
	total_max_to_read += rm;
	total_max_to_write += wm;
#define B(x) \
	if ((x) > max_bucket_level)		\
		max_bucket_level = (x);		\
	if ((x) < min_bucket_level)		\
		min_bucket_level = (x)
	B(r);
	B(w);
#undef B

	total_n_bev_checks++;
	if (total_n_bev_checks >= .8 * ((double)cfg_duration / cfg_tick_msec) * cfg_n_connections) {
		event_free(event_base_get_running_event(bufferevent_get_base(bev)));
	}
}
void on_event(struct bufferevent *bev, short event, void *arg){
    struct evbuffer *output = bufferevent_get_output(bev);
    struct event_base *base = bufferevent_get_base(bev);
    char buf[MAXLEN];
    //printf("event begin:%d\n", event);
    /*if(event & BEV_EVENT_READING){
        printf("Read?\n");
    }*/
    /*if(event & BEV_EVENT_WRITING){
        printf("Write?\n");
    }*/
    if(event & BEV_EVENT_EOF){
        //printf("EOF.\n");
        printf("Logged out.\n");
        pthread_cancel(tid);
        pthread_cancel(disptid);
        bufferevent_free(bev);
        event_base_loopexit(base, NULL);
    }
    if(event & BEV_EVENT_ERROR){
        printf("Error!\n");
    }
    if(event & BEV_EVENT_TIMEOUT){
        printf("Timeout!\n");
    }
    if(event & BEV_EVENT_CONNECTED){
        printf("Connected.\n");
        buf[0] = 0x80;
        buf[1] = user & 0xFF;
        *((package *)(&buf[2])) = pkg[user];
        evbuffer_add(output, buf, sizeof(pkg[user]) + 2);
    }
}
Пример #5
0
void bufferevent_cb(struct bufferevent *bev, short events, void *ptr)
{
    P_PORTTRANS p_trans = (P_PORTTRANS)ptr; 
    struct event_base *base = bufferevent_get_base(bev);

    //只有使用bufferevent_socket_connect进行的连接才会得到CONNECTED的事件
    if (events & BEV_EVENT_CONNECTED) 
    {
        st_d_print("GOT BEV_EVENT_CONNECTED event! ");
    } 
    else if (events & BEV_EVENT_ERROR) 
    {
        st_d_error("GOT BEV_EVENT_ERROR event[%d]! ", p_trans->l_port);

        sc_free_trans(p_trans);
    } 
    else if (events & BEV_EVENT_EOF) 
    {
        st_d_error("GOT BEV_EVENT_EOF event[%d]! ", p_trans->l_port); 

        sc_free_trans(p_trans);
    }
    else if (events & BEV_EVENT_TIMEOUT) 
    {
        st_d_error("GOT BEV_EVENT_TIMEOUT event[%d]! ", p_trans->l_port);

        sc_free_trans(p_trans);
    } 

    return;
}
Пример #6
0
void gated_error_cb(struct bufferevent *bev, short what, void *arg)
{
    struct event_base *base = bufferevent_get_base(bev);
    fprintf(stdout, "gated error cb!!!\n");
    int err = EVUTIL_SOCKET_ERROR();
    fprintf(stderr, "Got an error %d (%s) on the gated_error_cb."
            "Shutting down.\n", err, evutil_socket_error_to_string(err));
    event_base_loopexit(base, NULL);
}
Пример #7
0
static void maxconns_handler(const int fd, const short which, void *arg) {
    struct timeval t = {.tv_sec = 0, .tv_usec = 10000};

    if (fd == -42 || allow_new_conns == false) {
        /* reschedule in 10ms if we need to keep polling */
        evtimer_set(&maxconnsevent, maxconns_handler, 0);
        event_base_set(main_base, &maxconnsevent);
        evtimer_add(&maxconnsevent, &t);
    } else {
        evtimer_del(&maxconnsevent);
        accept_new_conns(true);
    }
}

static bool update_event(conn *c, const int new_flags) {
    assert(c != NULL);

    
    if (c->ev_flags == new_flags)
        return true;
    pthread_t tid = pthread_self();
    if (tid == dispatcher_thread.thread_id)
    {
        struct event_base *base = c->event.ev_base;
        if (event_del(&c->event) == -1) return false;    
        event_set(&c->event, c->sfd, new_flags, master_event_handler, (void *)c);
        event_base_set(base, &c->event);
        c->ev_flags = new_flags;
        if (event_add(&c->event, 0) == -1) return false;
        return true;
    }else{
        struct event_base *base = bufferevent_get_base(c->buf_ev);
        bufferevent_free(c->buf_ev);
        c->buf_ev = bufferevent_new(c->sfd, event_handler, buf_write_callback, buf_error_callback, (void * )c);
        bufferevent_base_set(base, c->buf_ev);
        
        c->ev_flags = new_flags;
        if (bufferevent_enable(c->buf_ev, new_flags) == -1) return false;
        return true;
    }    
    //这个也得改成bufferevent的形式
/*

    event_set(&c->event, c->sfd, new_flags, event_handler, (void *)c);
    event_base_set(base, &c->event);
    event_add(&c->event, 0);


    c->buf_ev = bufferevent_new(c->sfd, event_handler, event_handler, NULL, (void * )c);
    bufferevent_base_set(base, c->buf_ev);
    bufferevent_enable(c->buf_ev, new_flags);

    c->ev_flags = new_flags;
    if (event_add(&c->event, 0) == -1) return false;
    return true;
*/
}
Пример #8
0
/* Registers a ProxyServer with a ProxyClient, creating if it exists. */
void
cxmap_register(struct ProxyServer *serv)
{
    struct ProxyClient *client;
    if (!serv->path) {
        struct event_base *base = bufferevent_get_base(serv->bev);
        client = pclient_new(base, serv->location, NULL);
        g_debug("Creating a new ProxyClient object for %s", serv->location);
    } else {
        client = g_hash_table_lookup(tbl, serv->location);
        if (!client) {
            /* create new ProxyClient */
            struct event_base *base = bufferevent_get_base(serv->bev);
            client = pclient_new(base, serv->location, serv->path);
            g_hash_table_insert(tbl, client->location, client);
            g_debug("Creating a new ProxyClient object for %s", serv->location);
        } else {
            g_debug("Reusing an existing ProxyClient for %s", serv->location);
        }
    }
    pclient_register(client, serv);
}
Пример #9
0
void thread_bufferevent_cb(struct bufferevent *bev, short events, void *ptr)
{
    P_TRANS_ITEM p_trans = (P_TRANS_ITEM)ptr; 

    struct event_base *base = bufferevent_get_base(bev);
    int loop_terminate_flag = 0;

    //只有使用bufferevent_socket_connect进行的连接才会得到CONNECTED的事件
    if (events & BEV_EVENT_CONNECTED) 
    {
        st_d_print("GOT BEV_EVENT_CONNECTED event! ");
    } 
    else if (events & BEV_EVENT_ERROR) 
    {
        st_d_error("GOT BEV_EVENT_ERROR event[%d]! ", p_trans->usr_lport); 

        ss_free_trans(p_trans->p_activ_item, p_trans);
    } 
    else if (events & BEV_EVENT_EOF) 
    {
        st_d_print("GOT BEV_EVENT_EOF event[%d]! ", p_trans->usr_lport); 

        // 实际传输端结束,那么只针对这个传输,把对端的连接断开,
        // 由于TCP连接,那么对端的be_usr_srv和be_daemon_srv也会收到BEV_EVENT_EOF消息
        ss_free_trans(p_trans->p_activ_item, p_trans);

    }
    else if (events & BEV_EVENT_TIMEOUT) 
    {
        st_d_print("GOT BEV_EVENT_TIMEOUT event[%d]! ", p_trans->usr_lport); 

        ss_free_trans(p_trans->p_activ_item, p_trans);
    } 

    if (loop_terminate_flag)
    {
        bufferevent_free(bev);
        event_base_loopexit(base, NULL);
    }

    return;
}
Пример #10
0
/* Check that the server sends back the same byte that the client sent.
   If MAX_REQUESTS have been reached, exit. Otherwise, start another client. */
static void
client_read_cb(struct bufferevent *bev, void *ctx)
{
	unsigned char tmp;
	struct event_base *base = bufferevent_get_base(bev);

	bufferevent_read(bev, &tmp, 1);
	if (tmp != 'A') {
		puts("Incorrect data received!");
		exit(2);
	}
	bufferevent_free(bev);

	num_requests++;
	if (num_requests == MAX_REQUESTS) {
		event_base_loopbreak(base);
	} else {
		start_client(base);
	}
}
Пример #11
0
static void
on_peer_event(struct bufferevent* bev, short ev, void *arg)
{
	struct peer* p = (struct peer*)arg;
	
	if (ev & BEV_EVENT_CONNECTED) {
		paxos_log_info("Connected to %s:%d",
			inet_ntoa(p->addr.sin_addr), ntohs(p->addr.sin_port));
		p->status = ev;
	} else if (ev & BEV_EVENT_ERROR || ev & BEV_EVENT_EOF) {
		struct event_base* base;
		int err = EVUTIL_SOCKET_ERROR();
		paxos_log_error("%s (%s:%d)", evutil_socket_error_to_string(err),
			inet_ntoa(p->addr.sin_addr), ntohs(p->addr.sin_port));
		base = bufferevent_get_base(p->bev);
		bufferevent_free(p->bev);
		p->bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
		bufferevent_setcb(p->bev, on_read, NULL, on_peer_event, p);
		event_add(p->reconnect_ev, &reconnect_timeout);
		p->status = ev;
	} else {
		paxos_log_error("Event %d not handled", ev);
	}
}
Пример #12
0
struct bufferevent* red_connect_relay_ssl(const char *ifname,
                                    struct sockaddr_in *addr,
                                    SSL * ssl,
                                    bufferevent_data_cb readcb,
                                    bufferevent_data_cb writecb,
                                    bufferevent_event_cb errorcb,
                                    void *cbarg,
                                    const struct timeval *timeout_write)
{
    struct bufferevent *retval = NULL;
    struct bufferevent *underlying = NULL;
    int relay_fd = -1;
    int error;

    underlying = red_prepare_relay(ifname, NULL, NULL, NULL, NULL);
    if (!underlying)
        goto fail;
    relay_fd = bufferevent_getfd(underlying);
    if (timeout_write)
        bufferevent_set_timeouts(underlying, NULL, timeout_write);

    error = connect(relay_fd, (struct sockaddr*)addr, sizeof(*addr));
    if (error && errno != EINPROGRESS) {
        log_errno(LOG_NOTICE, "connect");
        goto fail;
    }
    retval = bufferevent_openssl_filter_new(bufferevent_get_base(underlying),
                                            underlying,
                                            ssl,
                                            BUFFEREVENT_SSL_CONNECTING,
                                            BEV_OPT_DEFER_CALLBACKS);
    if (!retval) {
        log_errno(LOG_NOTICE, "bufferevent_openssl_filter_new");
        goto fail;
    }
    if (timeout_write)
        bufferevent_set_timeouts(retval, NULL, timeout_write);

    bufferevent_setcb(retval, readcb, writecb, errorcb, cbarg);
    if (writecb) {
        error = bufferevent_enable(retval, EV_WRITE); // we wait for connection...
        if (error) {
            log_errno(LOG_ERR, "bufferevent_enable");
            goto fail;
        }
    }
    return retval;

fail:
    if (retval) {
        bufferevent_disable(retval, EV_READ|EV_WRITE);
        bufferevent_free(retval);
    }
    if (underlying) {
        bufferevent_disable(underlying, EV_READ|EV_WRITE);
        bufferevent_free(underlying);
    }
    if (relay_fd != -1)
        redsocks_close(relay_fd);
    return NULL;
}
Пример #13
0
static void smtp_conn_readcb(struct bufferevent *bev, void* args)
{
  struct evbuffer* buffer = bufferevent_get_input(bev);
  struct email* email = (struct email*) args;
  size_t len;
  char* line = evbuffer_readln(buffer, &len, EVBUFFER_EOL_CRLF);
  while (line) {
    if (email->mode != DATA) {
      if (string_equals(line, "QUIT"))
        bufferevent_write(bev, _221_BYE, strlen(_221_BYE));
      else if (string_equals(line, "RSET"))
        bufferevent_write(bev, _502_NOT_SUPPORTED, strlen(_502_NOT_SUPPORTED));
    }
    switch (email->mode) {
    case HEADERS:
      if (len >= 4 && !email->ehlo) { /* Could be an EHLO or HELO */
        if (string_startsWith(line, "EHLO") || string_startsWith(line, "HELO")) {
          email->ehlo = 1;
          bufferevent_write(bev, _250_OK, strlen(_250_OK));
        }
      } else if (email->ehlo) {
        if (!forEachCharacter(line, isEmailCharacters)) {
          if (string_startsWith(line, "MAIL FROM:<")) {
            char* addr = stripOutEmailAddress(line);
            if (addr) {
              char* query = create_check_email_from_query(addr);
              if (query)
                databaseQuery(query, check_email_from_callback, email);
              else
                bufferevent_write(bev, _550_NOT_ALLOWED, strlen(_550_NOT_ALLOWED));
              SAFEFREE(addr);
            } else
              bufferevent_write(bev, _550_NOT_ALLOWED, strlen(_550_NOT_ALLOWED));
          } else if (string_startsWith(line, "RCPT TO:<")) {
            char* addr = stripOutEmailAddress(line);
            if (addr) {
              char* query = create_check_email_to_query(addr);
              if (query)
                databaseQuery(query, check_email_to_callback, email);
              else
                bufferevent_write(bev, _550_NOT_ALLOWED, strlen(_550_NOT_ALLOWED));
              SAFEFREE(addr);
            } else
              bufferevent_write(bev, _550_NOT_ALLOWED, strlen(_550_NOT_ALLOWED));
          } else if (string_equals(line, "DATA")) {
            if (email_has_recipients(email)) {
              bufferevent_write(bev, _354_GO_AHEAD, strlen(_354_GO_AHEAD));
              email->mode = DATA_HEADERS;
            } else
              bufferevent_write(bev, _503_BAD_SEQUENCE, strlen(_503_BAD_SEQUENCE));
          } else
            bufferevent_write(bev, _550_NOT_ALLOWED, strlen(_550_NOT_ALLOWED));
        } else
          bufferevent_write(bev, _502_NOT_SUPPORTED, strlen(_502_NOT_SUPPORTED));
      }
      break;
    case DATA_HEADERS:
      if (strlen(line) == 0)
        email->mode = DATA;
      else if (!string_contains(line, ':')) {
        email->mode = DATA;
        email_append_data(email, line);
      } else if (string_startsWith(line, "Subject: "))
        email_set_subject(email, line);
      break;
    case DATA:
      if (strlen(line) > 0) {
        if (string_equals(line, ".")) {
          bufferevent_write(bev, _250_OK, strlen(_250_OK));
          email->mode = DATA_DONE;
          email_for_each_recipient(email, bufferevent_get_base(bev), launch_push_queries);
        } else
          email_append_data(email, line);
      }
      break;
    default:
      break;
    }
#ifdef DEV
    printf("I got the following line: %s\n", line);
#endif
    SAFEFREE(line);
    line = evbuffer_readln(buffer, &len, EVBUFFER_EOL_CRLF);
  }
}
Пример #14
0
int process_line(struct client* client, char* line, size_t len) {
  DEBUG(255, "Raw line: %s", line);
  char buf[65];
  double double_number;
  int number;
  struct timeval tv = { 0, 0 };
  if (strcmp(line, "MODULES") == 0)
    send_loaded_modules_info(client);
  else if (sscanf(line, "ENABLE %64s", buf) == 1) {
    struct module* module = get_module(buf);
    if (module) {
      struct enabled_mod* em = malloc(sizeof(struct enabled_mod));
      em->module = module;
      em->id = 0;
      em->next = NULL;
      if (!client->mods) {
        client->mods = em;
        if (em->module->array_length == 1)
          client_send_data(client, "LOADED: %s %s ID %d", module_type_to_string(em->module->type), buf, em->id);
        else
          client_send_data(client, "LOADED: %s %s ID %d WITH %d ITEMS", module_type_to_string(em->module->type), buf, em->id, em->module->array_length);
      } else {
        em->id++;
        struct enabled_mod* lm = client->mods;
        if (lm->module == em->module) {
          client_send_data(client, "ERROR: ALREADY LOADED %s WITH ID %d", em->module->name, em->id);
          free(em);
        } else {
          while (lm) {
            if (lm->module == em->module) {
              client_send_data(client, "ERROR: ALREADY LOADED %s WITH ID %d", em->module->name, em->id);
              free(em);
              return 0;
            }
            em->id = lm->id + 1;
            if (!lm->next)
              break;
            lm = lm->next;
          };
          lm->next = em;
          if (em->module->array_length == 1)
          client_send_data(client, "LOADED: %s %s ID %d", module_type_to_string(em->module->type), buf, em->id);
        else
          client_send_data(client, "LOADED: %s %s ID %d WITH %d ITEMS", module_type_to_string(em->module->type), buf, em->id, em->module->array_length);
        }
      }
    } else
      client_send_data(client, "ERROR: UNABLE TO LOAD %s", buf);
  } else if (sscanf(line, "DISABLE %64s", buf) == 1) {
    struct module* module = get_module(buf);
    if (module) {
      struct enabled_mod* lm = client->mods;
      if (lm->module == module) {
        client->mods = lm->next;
        client_send_data(client, "DISABLED: %s WITH ID %d", buf, lm->id);
        free(lm);
      } else {
        while (lm->next) {
          if (lm->next->module == module) {
            struct enabled_mod* to_free = lm->next;
            lm->next = lm->next->next;
            client_send_data(client, "DISABLED: %s WITH ID %d", buf, to_free->id);
            free(to_free);
            break;
          }
          lm = lm->next;
        };
      }
    } else
      client_send_data(client, "ERROR: MODULE %s DOESN'T EXIST", buf);
  } else if (sscanf(line, "PULL %64s", buf) == 1) {
    struct module* module = get_module(buf);
    if (module) {
      char databuf[BUFSIZ];
      if (update_value(module, databuf, sizeof(databuf), client))
        client_send_data(client, "%s: %s", module->name, databuf);
    };
  } else if (sscanf(line, "ITEMNAMES %64s", buf) == 1) {
    struct module* module = get_module(buf);
    if (module) {
      char databuf[BUFSIZ];
      if (get_module_item_names(module, databuf, sizeof(databuf)))
        client_send_data(client, "%s: %s", module->name, databuf);
    };
  } else if (sscanf(line, "INTERVAL %lf", &double_number) == 1) {
    if (client->timer)
      event_free(client->timer);
    if (double_number < 0) {
      client->timer = NULL;
      return 0;
    }
    tv.tv_sec = (long) double_number;
    tv.tv_usec = (long) ((double_number - (double) tv.tv_sec) * 1000000.0) ;
    client->timer = event_new(bufferevent_get_base(client->bev), -1, EV_PERSIST, client_timer, client);
    event_add(client->timer, &tv);
  } else if (sscanf(line, "PRECISION %d", &number) == 1) {
    if (number >= 0 && number <= 255)
      client->precision = number;
    else
      client_send_data(client, "ERROR: Precision %d is out of the valid range (0-255)", number);
  } else if ((!client->websocket || !client->websocket->connected) && handle_handshake(client, line, len))
    return 0;
  else {
    switch (++client->unknown_command) {
    case 1:
      client_send_data(client, "ERROR: This is not a valid command...");
      return 0;
    case 2:
      client_send_data(client, "ERROR: I'm warning you, stop that.");
      return 0;
    case 3:
      client_eventcb(client->bev, BEV_ERROR, client);
      return 1;
    }
  }
  client->unknown_command = 0;
  return 0;
};
Пример #15
0
void srv_bufferevent_cb(struct bufferevent *bev, short events, void *ptr)
{
    struct event_base *base = bufferevent_get_base(bev);
    int loop_terminate_flag = 0;

    //只有使用bufferevent_socket_connect进行的连接才会得到CONNECTED的事件
    if (events & BEV_EVENT_CONNECTED) 
    {
        st_d_print("GOT BEV_EVENT_CONNECTED event! ");
    } 
    else if (events & BEV_EVENT_ERROR) 
    {
        st_d_error("GOT BEV_EVENT_ERROR event! ");
        loop_terminate_flag = 1;
    } 
    else if (events & BEV_EVENT_EOF) 
    {
        st_d_print("GOT BEV_EVENT_EOF event! ");

        // main_be连接断开,这时候:如果是DAEMON端主动断开,那么USR端也要断开
        // 否则,就让DAEMON进行重置(重新连接服务器)
        // 任何情况下,所有的服务都必须断开

        // BEV_OPT_CLOSE_ON_FREE already closed the socket
        if (cltopt.C_TYPE == C_USR) 
        {
            st_d_print("DAEMON已经退出,本端挂起!");
            exit(EXIT_SUCCESS);
        }
        else
        {
            sc_free_all_trans();
            st_d_print("DAEMON端重连服务器!");

            int srv_fd;
            srv_fd = socket(AF_INET, SOCK_STREAM, 0);

            if (sc_connect_srv(srv_fd) != RET_YES)
            {
                st_d_error("连接服务器失败!");
                event_base_loopexit(base, NULL);
            }

            if (sc_daemon_init_srv(srv_fd) != RET_YES) 
            {
                st_d_error("(DAEMON)服务端返回错误!");
                event_base_loopexit(base, NULL);
            }
       
            sc_set_eventcb_srv(srv_fd, base);
            st_d_print("(DAEMON)重连OK!");

        }

    }
    else if (events & BEV_EVENT_TIMEOUT) 
    {
        st_d_print("GOT BEV_EVENT_TIMEOUT event! ");
    } 
    
    if (loop_terminate_flag)
    {
        bufferevent_free(bev);
        event_base_loopexit(base, NULL);
    }

    return;
}
Пример #16
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!");
        }
    }

}