original_code:
static int http_local_rev(struct fctl_session_t* session, char* buf , int buflen){
    int space = 0;
    if (session->proto_status != HTTP_INITIALIZED)
        goto ret;
    char * header_tail = strstr(buf , "\r\n\r\n");
    if ( header_tail == ((void *)0))
        return PROTO_RESERVED;
    session->proto_status = HTTP_HEADER_RECV;
   int header_len = header_tail - buf + 4;
 int left_len = buflen - header_len;
 char* left_content = ((void *)0);
 if (left_len > 0){
  char* left_content = (char*)malloc(left_len);
  memcpy(left_content, buf + header_len, left_len);
 }
 struct http_parser_t hp = {0};
 http_update_req(&hp, buf, header_len);
 char* new_url = strstr(hp.hlines[0].new_line, " ");
 if (new_url)
  new_url++;
 log_info("url: %s\n", new_url);;
 int need_proxy = url_need_proxy(new_url);
 if (session->remote_fd <= 0){
   int r = 0;
   if (need_proxy){
      char proxy_ip[32] = {0};
      new_sogou_proxy_addr(proxy_ip, sizeof(proxy_ip));
      printf(">>>proxy ip: %s\n", proxy_ip);
      r = session->proxy->remote_connect(session->proxy, session, proxy_ip[0] == 0?((void *)0):proxy_ip, 80);
       }else
          r = session->proxy->remote_connect(session->proxy, session, ((void *)0), 0);
     if (r < 0){
      if (left_content)
       free(left_content);
      http_parser_reset(&hp);
            return r;
        }
    }
    if (need_proxy){
  rwbuff_rewind_writep(&session->local_buf);
   int i = 0;
  for (; i < hp.cur_hline; i++) {
   char* line = ((void *)0);
   int line_len = 0;
   if (hp.hlines[i].new_line != ((void *)0)){
    line = hp.hlines[i].new_line;
    line_len = hp.hlines[i].new_line_len;
    log_debug("n %s", hp.hlines[i].new_line);;
   }else{
    line = hp.hlines[i].ori_line;
    line_len = hp.hlines[i].ori_line_len;
    log_debug("o %s", hp.hlines[i].ori_line);;
   }
   if (line){
    rwbuff_append_data(&session->local_buf, line, line_len);
   }
  }
  rwbuff_append_data(&session->local_buf, "\r\n", 2);
  if (left_content){
   rwbuff_append_data(&session->local_buf, left_content, left_len);
  }
 }
 http_parser_reset(&hp);
 if (left_content)
  free(left_content);
 ret:
    space = rwbuff_get_readn(&session->local_buf);
    rwbuff_read(&session->local_buf, space);
    return PROTO_SEND;
}

canonical_original_code:
static int http_local_rev(struct fctl_session_t *session, char *buf, int buflen){
    int space = 0;
    if (session->proto_status != HTTP_INITIALIZED)
        goto ret;
    char *header_tail = strstr(buf , "\r\n\r\n");
    if ( header_tail == ((void *)0))
        return PROTO_RESERVED;
    session->proto_status = HTTP_HEADER_RECV;
   int header_len = header_tail - buf + 4;
 int left_len = buflen - header_len;
 char *left_content = ((void *)0);
 if (left_len > 0){
  char *left_content = (char*)malloc(left_len);
  memcpy(left_content, buf + header_len, left_len);
 }
 struct http_parser_t hp = {0};
 http_update_req(&hp, buf, header_len);
 char *new_url = strstr(hp.hlines[0].new_line, " ");
 if (new_url)
  new_url++;
 log_info("url: %s\n", new_url);;
 int need_proxy = url_need_proxy(new_url);
 if (session->remote_fd <= 0){
   int r = 0;
   if (need_proxy){
      char proxy_ip[32] = {0};
      new_sogou_proxy_addr(proxy_ip, sizeof(proxy_ip));
      printf(">>>proxy ip: %s\n", proxy_ip);
      r = session->proxy->remote_connect(session->proxy, session, proxy_ip[0] == 0?((void *)0):proxy_ip, 80);
       }else
          r = session->proxy->remote_connect(session->proxy, session, ((void *)0), 0);
     if (r < 0){
      if (left_content)
       free(left_content);
      http_parser_reset(&hp);
            return r;
        }
    }
    if (need_proxy){
  rwbuff_rewind_writep(&session->local_buf);
   int i = 0;
  for (; i < hp.cur_hline; i++) {
   char *line = ((void *)0);
   int line_len = 0;
   if (hp.hlines[i].new_line != ((void *)0)){
    line = hp.hlines[i].new_line;
    line_len = hp.hlines[i].new_line_len;
    log_debug("n %s", hp.hlines[i].new_line);;
   }else{
    line = hp.hlines[i].ori_line;
    line_len = hp.hlines[i].ori_line_len;
    log_debug("o %s", hp.hlines[i].ori_line);;
   }
   if (line){
    rwbuff_append_data(&session->local_buf, line, line_len);
   }
  }
  rwbuff_append_data(&session->local_buf, "\r\n", 2);
  if (left_content){
   rwbuff_append_data(&session->local_buf, left_content, left_len);
  }
 }
 http_parser_reset(&hp);
 if (left_content)
  free(left_content);
 ret:
    space = rwbuff_get_readn(&session->local_buf);
    rwbuff_read(&session->local_buf, space);
    return PROTO_SEND;
}

variable_types: struct http_parser_t { int reqid; int uid; unsigned int pid; int net_protocol; union { struct sockaddr_in { unsigned short sin_family; unsigned short sin_port; struct in_addr { unsigned int s_addr; } sin_addr; unsigned char sin_zero[-1]; } addr4; struct sockaddr_in6 { unsigned short sin6_family; unsigned short sin6_port; unsigned int sin6_flowinfo; struct in6_addr { union { unsigned char __u6_addr8[16]; unsigned short __u6_addr16[8]; unsigned int __u6_addr32[4]; } __in6_u; } sin6_addr; unsigned int sin6_scope_id; } addr6; } local; union { struct sockaddr_in addr4; struct sockaddr_in6 addr6; } remote; char host[64]; int urllen; char url[1024]; char cache_line[2048]; int cache_line_index; short status; char http_version_str[16]; char method[16]; int safe_search_enabled; struct header_line_t { int type; char *ori_line; int ori_line_len; char *new_line; int new_line_len; } hlines[32]; int cur_hline; int hostlen; }

variable_types: r int

variable_types: i int

variable_types:
line
char *

user_defined_types: struct http_parser_t { int reqid; int uid; unsigned int pid; int net_protocol; union { struct sockaddr_in addr4; struct sockaddr_in6 addr6; } local; union { struct sockaddr_in addr4; struct sockaddr_in6 addr6; } remote; char host[64]; int urllen; char url[1024]; char cache_line[2048]; int cache_line_index; short status; char http_version_str[16]; char method[16]; int safe_search_enabled; struct header_line_t hlines[32]; int cur_hline; int hostlen; }

user_defined_types: struct sockaddr_in6 { unsigned short sin6_family; unsigned short sin6_port; unsigned int sin6_flowinfo; struct in6_addr sin6_addr; unsigned int sin6_scope_id; }


repo: dzli/hproxy

decompiled_code:
_QWORD *http_new()
{
_QWORD *result; // rax

result = malloc(0x48uLL);
if ( result )
{
*result = 0LL;
result[1] = 0LL;
result[2] = 0LL;
result[3] = 0LL;
result[8] = 0LL;
*(_DWORD *)result = 1347703880;
*((_DWORD *)result + 5) = 80;
result[6] = http_connect;
result[7] = http_disconnect;
result[4] = http_local_rev;
result[5] = http_remote_rev;
}
return result;
}

canonical_decompiled_code:
_QWORD *func4()
{
_QWORD *result; // rax

result = malloc(0x48uLL);
if ( result )
{
*result = 0LL;
result[1] = 0LL;
result[2] = 0LL;
result[3] = 0LL;
result[8] = 0LL;
*(_DWORD *)result = 1347703880;
*((_DWORD *)result + 5) = 80;
result[6] = http_connect;
result[7] = http_disconnect;
result[4] = http_local_rev;
result[5] = http_remote_rev;
}
return result;
}

original_code:
struct fctl_proto_t * http_new(void){
    struct fctl_proto_t* ret = ((void *)0);
    ret = (struct fctl_proto_t*)malloc(sizeof(struct fctl_proto_t));
    if (ret == ((void *)0))
        return ((void *)0);
    memset(ret , 0 , sizeof(struct fctl_proto_t));
    strcpy(ret->proto_name, "HTTP");
    ret->port = 80;
    ret->on_connect= http_connect;
    ret->on_disconnect= http_disconnect;
    ret->on_local_rev= http_local_rev;
    ret->on_remote_rev= http_remote_rev;
    return ret;
}

canonical_original_code:
struct fctl_proto_t *http_new(){
    struct fctl_proto_t *ret = ((void *)0);
    ret = (struct fctl_proto_t *)malloc(sizeof(struct fctl_proto_t));
    if (ret == ((void *)0))
        return ((void *)0);
    memset(ret , 0 , sizeof(struct fctl_proto_t));
    strcpy(ret->proto_name, "HTTP");
    ret->port = 80;
    ret->on_connect= http_connect;
    ret->on_disconnect= http_disconnect;
    ret->on_local_rev= http_local_rev;
    ret->on_remote_rev= http_remote_rev;
    return ret;
}

variable_types: struct fctl_proto_t { char proto_name[20]; int port; enum PROXY_TYPE { PROXY_SYN=0, PROXY_ASY=1 } proxy_type; int (*on_local_rev)(struct fctl_session_t { struct list_head { struct list_head *next; } list; struct fctl_proxy_t { int daemon; int port; int pid; struct fctl_proto_t *proto; int valid_port; int max_bind_port; int min_bind_port; char proto_name[20]; unsigned int cur_session_id; struct list_head session_head; int (*run)(struct fctl_proxy_t *); int (*get_port)(struct fctl_proxy_t *); int (*read)(int, char *, int); int (*write)(int, char *, int); int (*listen)(struct fctl_proxy_t *); int (*local_send)(struct fctl_proxy_t *, struct fctl_session_t *); int (*remote_send)(struct fctl_proxy_t *, struct fctl_session_t *); int (*local_close)(struct fctl_proxy_t *, struct fctl_session_t *); int (*remote_close)(struct fctl_proxy_t *, struct fctl_session_t *); int (*remote_connect)(struct fctl_proxy_t *, struct fctl_session_t *, char *, int); } *proxy; int local_fd; int remote_fd; struct sockaddr_in { unsigned short sin_family; unsigned short sin_port; struct in_addr { unsigned int s_addr; } sin_addr; unsigned char sin_zero[-1]; } local_addr; int remote_src_port; int remote_dst_port; struct sockaddr_in remote_addr; struct rwbuff_t { char buf[-1]; char *readp; char *writep; char *sendp; int buf_len; int buf_default_len; struct cache_pool_t { int cache_count; struct list_head cache_head; } cache_pool; } local_buf; struct rwbuff_t remote_buf; int remote_status; int local_status; int proto_status; int local_retry_times; int remote_retry_times; void *private_data; long create_time; int closing_time; struct fctl_spool_t { int fd; char name[512]; int size; int exists; } spool; int session_id; int (*on_local_recv)(struct fctl_session_t *); int (*on_remote_recv)(struct fctl_session_t *); int (*on_local_send)(struct fctl_session_t *); int (*on_remote_send)(struct fctl_session_t *); int (*on_local_close)(struct fctl_session_t *); int (*on_local_connect)(struct fctl_session_t *); int (*on_remote_close)(struct fctl_session_t *); int (*on_remote_connect)(struct fctl_session_t *); int (*is_closed)(struct fctl_session_t *); int (*close)(struct fctl_session_t *); int (*free)(struct fctl_session_t *); } *, char *, int); int (*on_remote_rev)(struct fctl_session_t *, char *, int); int (*on_connect)(struct fctl_session_t *); int (*on_disconnect)(struct fctl_session_t *); int (*on_notification)(struct fctl_session_t *, struct event_header_t { int session_id; int event_type; int event_len; } *); } *

user_defined_types: struct fctl_proto_t { char proto_name[20]; int port; enum PROXY_TYPE proxy_type; int (*on_local_rev)(struct fctl_session_t *, char *, int); int (*on_remote_rev)(struct fctl_session_t *, char *, int); int (*on_connect)(struct fctl_session_t *); int (*on_disconnect)(struct fctl_session_t *); int (*on_notification)(struct fctl_session_t *, struct event_header_t *); }

user_defined_types: struct fctl_session_t { struct list_head list; struct fctl_proxy_t *proxy; int local_fd; int remote_fd; struct sockaddr_in local_addr; int remote_src_port; int remote_dst_port; struct sockaddr_in remote_addr; struct rwbuff_t local_buf; struct rwbuff_t remote_buf; int remote_status; int local_status; int proto_status; int local_retry_times; int remote_retry_times; void *private_data; long create_time; int closing_time; struct fctl_spool_t spool; int session_id; int (*on_local_recv)(struct fctl_session_t *); int (*on_remote_recv)(struct fctl_session_t *); int (*on_local_send)(struct fctl_session_t *); int (*on_remote_send)(struct fctl_session_t *); int (*on_local_close)(struct fctl_session_t *); int (*on_local_connect)(struct fctl_session_t *); int (*on_remote_close)(struct fctl_session_t *); int (*on_remote_connect)(struct fctl_session_t *); int (*is_closed)(struct fctl_session_t *); int (*close)(struct fctl_session_t *); int (*free)(struct fctl_session_t *); }

user_defined_types: struct sockaddr_in { unsigned short sin_family; unsigned short sin_port; struct in_addr sin_addr; unsigned char sin_zero[-1]; }

user_defined_types: struct rwbuff_t { char buf[-1]; char *readp; char *writep; char *sendp; int buf_len; int buf_default_len; struct cache_pool_t cache_pool; }


decompiled_code:
void sig_term()
{
stop = 1;
}

canonical_decompiled_code:
void func1()
{
stop = 1;
}

original_code:
static void sig_term(int signo)
{
    stop = 1;
}

variable_types: signo int

return_type: void


start

decompiled_code:
unsigned int start()
{
unsigned int v0; // eax
int v1; // edi
int v2; // edi
__int64 v4; // rax
__int64 v5; // rax
__int64 v6; // rdi
__int64 v7; // rbx

signal(13, (__sighandler_t)sig_term);
signal(1, sig_reload_config);
atexit((void (*)(void))on_exit);
init_iptables_nat_rules();
memset(&proxies, 0, (size_t)&unk_18260);
if ( *(_DWORD *)&g_conf[2056] )
{
v4 = http_new();
v5 = np_new(v4, *(unsigned int *)&g_conf[2100], *(unsigned int *)&g_conf[2108], *(unsigned int *)&g_conf[2104]);
pc_add_proxy(&proxies, v5);
v6 = *(unsigned int *)&g_conf[2060];
if ( (_DWORD)v6 )
{
v7 = (unsigned int)((_DWORD)g_conf + 2064);
do
{
create_iptables_nat_rule(v6, *(unsigned int *)&g_conf[2100]);
v7 += 4LL;
v6 = *(unsigned int *)(v7 - 4);
}
while ( (_DWORD)v6 );
}
}
pc_run_all(&proxies);
signal(15, (__sighandler_t)sig_term);
signal(2, (__sighandler_t)sig_term);
signal(17, sig_chld);
while ( !stop )
pause();
v0 = getpid();
printf("pid= %d\n", v0);
pc_kill_all(&proxies, 15LL);
v1 = 2;
do
v1 = sleep(v1);
while ( v1 );
pc_kill_all(&proxies, 9LL);
v2 = 1;
do
v2 = sleep(v2);
while ( v2 );
log_info(" FortiClient stopped.\n");
unlink((const char *)(unsigned int)((_DWORD)g_conf + 512));
destroy_iptables_nat_rules();
return sleep(1u);
}

canonical_decompiled_code:
unsigned int func3()
{
unsigned int v0; // eax
int v1; // edi
int v2; // edi
__int64 v4; // rax
__int64 v5; // rax
__int64 v6; // rdi
__int64 v7; // rbx

signal(13, (__sighandler_t)sig_term);
signal(1, sig_reload_config);
atexit((void (*)(void))on_exit);
init_iptables_nat_rules();
memset(&proxies, 0, (size_t)&unk_18260);
if ( *(_DWORD *)&g_conf[2056] )
{
v4 = http_new();
v5 = np_new(v4, *(unsigned int *)&g_conf[2100], *(unsigned int *)&g_conf[2108], *(unsigned int *)&g_conf[2104]);
pc_add_proxy(&proxies, v5);
v6 = *(unsigned int *)&g_conf[2060];
if ( (_DWORD)v6 )
{
v7 = (unsigned int)((_DWORD)g_conf + 2064);
do
{
create_iptables_nat_rule(v6, *(unsigned int *)&g_conf[2100]);
v7 += 4LL;
v6 = *(unsigned int *)(v7 - 4);
}
while ( (_DWORD)v6 );
}
}
pc_run_all(&proxies);
signal(15, (__sighandler_t)sig_term);
signal(2, (__sighandler_t)sig_term);
signal(17, sig_chld);
while ( !stop )
pause();
v0 = getpid();
printf("pid= %d\n", v0);
pc_kill_all(&proxies, 15LL);
v1 = 2;
do
v1 = sleep(v1);
while ( v1 );
pc_kill_all(&proxies, 9LL);
v2 = 1;
do
v2 = sleep(v2);
while ( v2 );
log_info(" FortiClient stopped.\n");
unlink((const char *)(unsigned int)((_DWORD)g_conf + 512));
destroy_iptables_nat_rules();
return sleep(1u);
}

original_code:
static void start(){
    signal(13 , ((__sighandler_t) 1) );
    signal(1 , sig_reload_config);
 atexit(_on_exit);
    init_iptables_nat_rules();
    memset(&proxies ,0 , sizeof(proxies));
    if (g_conf.enable_http){ struct fctl_proto_t* http_proto = http_new(); struct fctl_proxy_t* http_proxy = np_new( http_proto, g_conf.http_proxy_listen_port, g_conf.http_max_bind_port , g_conf.http_min_bind_port); pc_add_proxy(&proxies , http_proxy); int i = 0; while(g_conf.http_ports[i] != 0){ create_iptables_nat_rule(g_conf.http_ports[i] , g_conf.http_proxy_listen_port); i++; } };
   pc_run_all(&proxies);
    signal(15 , sig_term);
    signal(2, sig_term);
    signal(17, sig_chld);
    while(!stop)
     pause();
    printf("pid= %d\n", getpid());
    pc_kill_all(&proxies, 15);
    unsigned int unsleep = 2;
    while(unsleep > 0){
        unsleep = sleep(unsleep);
    }
    pc_kill_all(&proxies, 9);
    unsleep = 1;
    while(unsleep > 0){
        unsleep = sleep(unsleep);
    }
    log_info(" FortiClient stopped.\n");;
    unlink(g_conf.pid_file);
    destroy_iptables_nat_rules();
   sleep(1);
}

canonical_original_code:
static void start(){
    signal(13 , ((void (*)(int)) 1) );
    signal(1 , sig_reload_config);
 atexit(_on_exit);
    init_iptables_nat_rules();
    memset(&proxies ,0 , sizeof(proxies));
    if (g_conf.enable_http){ struct fctl_proto_t *http_proto = http_new(); struct fctl_proxy_t *http_proxy = np_new( http_proto, g_conf.http_proxy_listen_port, g_conf.http_max_bind_port , g_conf.http_min_bind_port); pc_add_proxy(&proxies , http_proxy); int i = 0; while(g_conf.http_ports[i] != 0){ create_iptables_nat_rule(g_conf.http_ports[i] , g_conf.http_proxy_listen_port); i++; } };
   pc_run_all(&proxies);
    signal(15 , sig_term);
    signal(2, sig_term);
    signal(17, sig_chld);
    while(!stop)
     pause();
    printf("pid= %d\n", getpid());
    pc_kill_all(&proxies, 15);
    unsigned int unsleep = 2;
    while(unsleep > 0){
        unsleep = sleep(unsleep);
    }
    pc_kill_all(&proxies, 9);
    unsleep = 1;
    while(unsleep > 0){
        unsleep = sleep(unsleep);
    }
    log_info(" FortiClient stopped.\n");;
    unlink(g_conf.pid_file);
    destroy_iptables_nat_rules();
   sleep(1);
}

variable_types: struct fctl_proxy_t { int daemon; int port; int pid; struct fctl_proto_t { char proto_name[20]; int port; enum PROXY_TYPE { PROXY_SYN=0, PROXY_ASY=1 } proxy_type; int (*on_local_rev)(struct fctl_session_t { struct list_head { struct list_head *next; } list; struct fctl_proxy_t *proxy; int local_fd; int remote_fd; struct sockaddr_in { unsigned short sin_family; unsigned short sin_port; struct in_addr { unsigned int s_addr; } sin_addr; unsigned char sin_zero[-1]; } local_addr; int remote_src_port; int remote_dst_port; struct sockaddr_in remote_addr; struct rwbuff_t { char buf[-1]; char *readp; char *writep; char *sendp; int buf_len; int buf_default_len; struct cache_pool_t { int cache_count; struct list_head cache_head; } cache_pool; } local_buf; struct rwbuff_t remote_buf; int remote_status; int local_status; int proto_status; int local_retry_times; int remote_retry_times; void *private_data; long create_time; int closing_time; struct fctl_spool_t { int fd; char name[512]; int size; int exists; } spool; int session_id; int (*on_local_recv)(struct fctl_session_t *); int (*on_remote_recv)(struct fctl_session_t *); int (*on_local_send)(struct fctl_session_t *); int (*on_remote_send)(struct fctl_session_t *); int (*on_local_close)(struct fctl_session_t *); int (*on_local_connect)(struct fctl_session_t *); int (*on_remote_close)(struct fctl_session_t *); int (*on_remote_connect)(struct fctl_session_t *); int (*is_closed)(struct fctl_session_t *); int (*close)(struct fctl_session_t *); int (*free)(struct fctl_session_t *); } *, char *, int); int (*on_remote_rev)(struct fctl_session_t *, char *, int); int (*on_connect)(struct fctl_session_t *); int (*on_disconnect)(struct fctl_session_t *); int (*on_notification)(struct fctl_session_t *, struct event_header_t { int session_id; int event_type; int event_len; } *); } *proto; int valid_port; int max_bind_port; int min_bind_port; char proto_name[20]; unsigned int cur_session_id; struct list_head session_head; int (*run)(struct fctl_proxy_t *); int (*get_port)(struct fctl_proxy_t *); int (*read)(int, char *, int); int (*write)(int, char *, int); int (*listen)(struct fctl_proxy_t *); int (*local_send)(struct fctl_proxy_t *, struct fctl_session_t *); int (*remote_send)(struct fctl_proxy_t *, struct fctl_session_t *); int (*local_close)(struct fctl_proxy_t *, struct fctl_session_t *); int (*remote_close)(struct fctl_proxy_t *, struct fctl_session_t *); int (*remote_connect)(struct fctl_proxy_t *, struct fctl_session_t *, char *, int); } *

variable_types:
unsleep
unsigned int

user_defined_types: struct fctl_proxy_t { int daemon; int port; int pid; struct fctl_proto_t *proto; int valid_port; int max_bind_port; int min_bind_port; char proto_name[20]; unsigned int cur_session_id; struct list_head session_head; int (*run)(struct fctl_proxy_t *); int (*get_port)(struct fctl_proxy_t *); int (*read)(int, char *, int); int (*write)(int, char *, int); int (*listen)(struct fctl_proxy_t *); int (*local_send)(struct fctl_proxy_t *, struct fctl_session_t *); int (*remote_send)(struct fctl_proxy_t *, struct fctl_session_t *); int (*local_close)(struct fctl_proxy_t *, struct fctl_session_t *); int (*remote_close)(struct fctl_proxy_t *, struct fctl_session_t *); int (*remote_connect)(struct fctl_proxy_t *, struct fctl_session_t *, char *, int); }


decompiled_code:
void sig_chld()
{
__pid_t v0; // eax
unsigned int v1; // ebx
int stat_loc[3]; // [rsp+Ch] [rbp-Ch] BYREF

while ( 1 )
{
v0 = waitpid(-1, stat_loc, 1);
v1 = v0;
if ( v0 <= 0 )
break;
printf("daemon %d terminated.\n", (unsigned int)v0);
log_info("proxy %d terminated", v1);
if ( stop )
pc_remove_pid(&proxies, v1);
else
pc_restart_others(&proxies, v1);
}
}

canonical_decompiled_code:
void func5()
{
__pid_t v0; // eax
unsigned int v1; // ebx
int stat_loc[3]; // [rsp+Ch] [rbp-Ch] BYREF

while ( 1 )
{
v0 = waitpid(-1, stat_loc, 1);
v1 = v0;
if ( v0 <= 0 )
break;
printf("daemon %d terminated.\n", (unsigned int)v0);
log_info("proxy %d terminated", v1);
if ( stop )
pc_remove_pid(&proxies, v1);
else
pc_restart_others(&proxies, v1);
}
}

original_code:
void sig_chld(int signo){
    pid_t pid;
    int stat;
    while ( (pid = waitpid(-1, &stat, 1)) > 0){
        printf("daemon %d terminated.\n", pid);
        log_info("proxy %d terminated", pid);;
        if (!stop)
            pc_restart_others(&proxies, pid);
        else
            pc_remove_pid(&proxies, pid);
    }
    return;
}

canonical_original_code:
void sig_chld(int signo){
    int pid;
    int stat;
    while ( (pid = waitpid(-1, &stat, 1)) > 0){
        printf("daemon %d terminated.\n", pid);
        log_info("proxy %d terminated", pid);;
        if (!stop)
            pc_restart_others(&proxies, pid);
        else
            pc_remove_pid(&proxies, pid);
    }
    return;
}

variable_types: pid int

variable_types: stat int


daemonize

decompiled_code:
int daemonize()
{
__pid_t v0; // eax
__pid_t v1; // eax
rlim_t v2; // rbx
struct sigaction v4; // [rsp+0h] [rbp-B8h] BYREF
struct rlimit rlimits; // [rsp+A0h] [rbp-18h] BYREF

umask(0);
if ( getrlimit(RLIMIT_NOFILE, &rlimits) < 0 )
{
log_error("can't get file limit");
exit(-1);
}
v0 = fork();
if ( v0 < 0 )
{
log_error("can't fork");
exit(-2);
}
if ( v0 )
exit(0);
setsid();
v4.sa_handler = (__sighandler_t)sig_term;
sigemptyset(&v4.sa_mask);
v4.sa_flags = 0;
if ( sigaction(1, &v4, 0LL) < 0 )
{
log_error("can't ignore SIGHUP");
exit(-3);
}
v1 = fork();
if ( v1 < 0 )
{
log_error("can't fork");
exit(-2);
}
if ( v1 )
exit(0);
if ( rlimits.rlim_max == -1LL )
{
rlimits.rlim_max = 1024LL;
}
else if ( !rlimits.rlim_max )
{
goto LABEL_14;
}
v2 = 0LL;
do
close(v2++);
while ( rlimits.rlim_max > v2 );
LABEL_14:
open("/dev/null", 0);
open("/dev/null", 0);
return open("/dev/null", 0);
}

canonical_decompiled_code:
int func6()
{
__pid_t v0; // eax
__pid_t v1; // eax
rlim_t v2; // rbx
struct sigaction v4; // [rsp+0h] [rbp-B8h] BYREF
struct rlimit rlimits; // [rsp+A0h] [rbp-18h] BYREF

umask(0);
if ( getrlimit(RLIMIT_NOFILE, &rlimits) < 0 )
{
log_error("can't get file limit");
exit(-1);
}
v0 = fork();
if ( v0 < 0 )
{
log_error("can't fork");
exit(-2);
}
if ( v0 )
exit(0);
setsid();
v4.sa_handler = (__sighandler_t)sig_term;
sigemptyset(&v4.sa_mask);
v4.sa_flags = 0;
if ( sigaction(1, &v4, 0LL) < 0 )
{
log_error("can't ignore SIGHUP");
exit(-3);
}
v1 = fork();
if ( v1 < 0 )
{
log_error("can't fork");
exit(-2);
}
if ( v1 )
exit(0);
if ( rlimits.rlim_max == -1LL )
{
rlimits.rlim_max = 1024LL;
}
else if ( !rlimits.rlim_max )
{
goto LABEL_14;
}
v2 = 0LL;
do
close(v2++);
while ( rlimits.rlim_max > v2 );
LABEL_14:
open("/dev/null", 0);
open("/dev/null", 0);
return open("/dev/null", 0);
}

original_code:
void daemonize(){
    int i;
    pid_t pid;
    struct rlimit rl;
    struct sigaction sa;
    umask(0);
    if (getrlimit(RLIMIT_NOFILE, &rl) < 0){
        log_error("can't get file limit");;
        exit(-1);
    }
    if ((pid = fork()) < 0){
        log_error("can't fork");;
        exit(-2);
    }
    else if (pid != 0)
        exit(0);
    setsid();
    sa.__sigaction_handler.sa_handler = ((__sighandler_t) 1);
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    if (sigaction(1, &sa, ((void *)0)) < 0){
        log_error("can't ignore SIGHUP");;
        exit(-3);
    }
    if ((pid = fork()) < 0){
        log_error("can't fork");;
        exit(-2);
    }
    else if (pid != 0)
        exit(0);
    if (rl.rlim_max == ((__rlim_t) -1))
        rl.rlim_max = 1024;
    for (i = 0; i < rl.rlim_max; i++)
        close(i);
    open("/dev/null", 00);
    open("/dev/null", 00);
    open("/dev/null", 00);
}

canonical_original_code:
void daemonize(){
    int i;
    int pid;
    struct rlimit rl;
    struct sigaction sa;
    umask(0);
    if (getrlimit(RLIMIT_NOFILE, &rl) < 0){
        log_error("can't get file limit");;
        exit(-1);
    }
    if ((pid = fork()) < 0){
        log_error("can't fork");;
        exit(-2);
    }
    else if (pid != 0)
        exit(0);
    setsid();
    sa.__sigaction_handler.sa_handler = ((void (*)(int)) 1);
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    if (sigaction(1, &sa, ((void *)0)) < 0){
        log_error("can't ignore SIGHUP");;
        exit(-3);
    }
    if ((pid = fork()) < 0){
        log_error("can't fork");;
        exit(-2);
    }
    else if (pid != 0)
        exit(0);
    if (rl.rlim_max == ((__rlim_t) -1))
        rl.rlim_max = 1024;
    for (i = 0; i < rl.rlim_max; i++)
        close(i);
    open("/dev/null", 00);
    open("/dev/null", 00);
    open("/dev/null", 00);
}

variable_types: struct rlimit { unsigned long rlim_cur; unsigned long rlim_max; }

variable_types: struct sigaction { union { void (*sa_handler)(int); void (*sa_sigaction)(int, struct siginfo_t { int si_signo; int si_errno; int si_code; int __pad0; union { int _pad[-1]; struct { int si_pid; unsigned int si_uid; } _kill; struct { int si_tid; int si_overrun; union sigval { int sival_int; void *sival_ptr; } si_sigval; } _timer; struct { int si_pid; unsigned int si_uid; union sigval si_sigval; } _rt; struct { int si_pid; unsigned int si_uid; int si_status; long si_utime; long si_stime; } _sigchld; struct { void *si_addr; short si_addr_lsb; union { struct { void *_lower; void *_upper; } _addr_bnd; unsigned int _pkey; } _bounds; } _sigfault; struct { long si_band; int si_fd; } _sigpoll; struct { void *_call_addr; int _syscall; unsigned int _arch; } _sigsys; } _sifields; } *, void *); } __sigaction_handler; struct __sigset_t { unsigned long __val[-1]; } sa_mask; int sa_flags; void (*sa_restorer)(); }

user_defined_types: struct sigaction { union { void (*sa_handler)(int); void (*sa_sigaction)(int, struct siginfo_t *, void *); } __sigaction_handler; struct __sigset_t sa_mask; int sa_flags; void (*sa_restorer)(); }

user_defined_types: struct siginfo_t { int si_signo; int si_errno; int si_code; int __pad0; union { int _pad[-1]; struct { int si_pid; unsigned int si_uid; } _kill; struct { int si_tid; int si_overrun; union sigval si_sigval; } _timer; struct { int si_pid; unsigned int si_uid; union sigval si_sigval; } _rt; struct { int si_pid; unsigned int si_uid; int si_status; long si_utime; long si_stime; } _sigchld; struct { void *si_addr; short si_addr_lsb; union { struct { void *_lower; void *_upper; } _addr_bnd; unsigned int _pkey; } _bounds; } _sigfault; struct { long si_band; int si_fd; } _sigpoll; struct { void *_call_addr; int _syscall; unsigned int _arch; } _sigsys; } _sifields; }


main

canonical_name: main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // eax
const char **v4; // rdx
const char *v5; // rbp
int v6; // ebx
int v7; // eax
int v9; // eax
__pid_t v10; // er12
__int64 v11; // rbx

memset(&proxies, 0, (size_t)&unk_18260);
strcpy(g_configfile, "/etc/forticlient.conf");
while ( 1 )
{
v3 = getopt_long(argc, (char *const *)argv, "hvc:l:f", &long_options_0, 0LL);
if ( v3 == -1 )
break;
switch ( v3 )
{
case 'c':
strcpy(g_configfile, optarg);
break;
case 'f':
g_foregound = 1;
break;
case 'h':
usage();
exit(0);
case 'l':
g_log_level = atoi(optarg);
break;
case 'v':
printf("hproxy %s\n", "V3.0.0");
exit(0);
default:
usage();
exit(-2);
}
}
v4 = &argv[optind];
if ( argc - optind <= 0 || (v5 = *v4) == 0LL )
{
usage();
exit(-2);
}
v6 = load_conf(g_conf, g_configfile);
if ( v6 )
{
log_error("read config file %s error!", g_configfile);
v6 = -3;
}
else
{
if ( g_log_level < 0 )
g_log_level = *(_DWORD *)&g_conf[2052];
if ( g_foregound )
log_init_ex((unsigned int)g_log_level, 0LL, (unsigned int)((_DWORD)g_conf + 1024), 3LL);
else
log_init_ex((unsigned int)g_log_level, 0LL, (unsigned int)((_DWORD)g_conf + 1024), 2LL);
if ( !strcasecmp(v5, "start") )
{
if ( !g_foregound )
daemonize();
printf("pid file: %s\n", (const char *)(unsigned int)((_DWORD)g_conf + 512));
v7 = write_pid((unsigned int)((_DWORD)g_conf + 512));
if ( !v7 )
{
start();
return 0;
}
if ( v7 <= 0 )
return -4;
log_error("forticlient proxy has already run!");
}
if ( !strcasecmp(v5, "stop") )
{
v9 = get_pid((unsigned int)((_DWORD)g_conf + 512));
v10 = v9;
if ( v9 > 0 )
{
log_debug("pid = %d", (unsigned int)v9);
kill(v10, 15);
}
}
if ( !strcasecmp(v5, "reload") )
{
v11 = (unsigned int)get_pid((unsigned int)((_DWORD)g_conf + 512));
log_debug("pid = %d", v11);
kill(v11, 1);
v6 = 0;
}
}
return v6;
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // eax
const char **v4; // rdx
const char *v5; // rbp
int v6; // ebx
int v7; // eax
int v9; // eax
__pid_t v10; // er12
__int64 v11; // rbx

memset(&proxies, 0, (size_t)&unk_18260);
strcpy(g_configfile, "/etc/forticlient.conf");
while ( 1 )
{
v3 = getopt_long(argc, (char *const *)argv, "hvc:l:f", &long_options_0, 0LL);
if ( v3 == -1 )
break;
switch ( v3 )
{
case 'c':
strcpy(g_configfile, optarg);
break;
case 'f':
g_foregound = 1;
break;
case 'h':
func2();
exit(0);
case 'l':
g_log_level = atoi(optarg);
break;
case 'v':
printf("hproxy %s\n", "V3.0.0");
exit(0);
default:
func2();
exit(-2);
}
}
v4 = &argv[optind];
if ( argc - optind <= 0 || (v5 = *v4) == 0LL )
{
func2();
exit(-2);
}
v6 = load_conf(g_conf, g_configfile);
if ( v6 )
{
log_error("read config file %s error!", g_configfile);
v6 = -3;
}
else
{
if ( g_log_level < 0 )
g_log_level = *(_DWORD *)&g_conf[2052];
if ( g_foregound )
log_init_ex((unsigned int)g_log_level, 0LL, (unsigned int)((_DWORD)g_conf + 1024), 3LL);
else
log_init_ex((unsigned int)g_log_level, 0LL, (unsigned int)((_DWORD)g_conf + 1024), 2LL);
if ( !strcasecmp(v5, "start") )
{
if ( !g_foregound )
func6();
printf("pid file: %s\n", (const char *)(unsigned int)((_DWORD)g_conf + 512));
v7 = write_pid((unsigned int)((_DWORD)g_conf + 512));
if ( !v7 )
{
func3();
return 0;
}
if ( v7 <= 0 )
return -4;
log_error("forticlient proxy has already run!");
}
if ( !strcasecmp(v5, "stop") )
{
v9 = get_pid((unsigned int)((_DWORD)g_conf + 512));
v10 = v9;
if ( v9 > 0 )
{
log_debug("pid = %d", (unsigned int)v9);
kill(v10, 15);
}
}
if ( !strcasecmp(v5, "reload") )
{
v11 = (unsigned int)get_pid((unsigned int)((_DWORD)g_conf + 512));
log_debug("pid = %d", v11);
kill(v11, 1);
v6 = 0;
}
}
return v6;
}

original_code:
int main(int argc , char* argv[]){
    int err = 0 , found_config = 0 , c = 0;
    char* cmd = ((void *)0);
    extern char * optarg;
    extern int optind;
    const char *short_options = "hvc:l:f";
    static struct option long_options [] ={
     {"help", 0, ((void *)0), 'h' },
     {"version", 0, ((void *)0), 'v' },
     {"config", 1, ((void *)0), 'c' },
     {"log", 1, ((void *)0), 'l' },
     {"foreground", 0, ((void *)0), 'f' },
     {((void *)0), 0, ((void *)0), 0 }
    };
    memset(&proxies, 0 , sizeof(proxies));
    strcpy(g_configfile , "/etc/forticlient.conf");
    while ((c=getopt_long(argc, argv, short_options,long_options,((void *)0))) != -1){
        switch (c){
        case 'v':
            printf("hproxy  %s\n", "V3.0.0");
            exit(0);
            break;
        case 'h':
            usage(argv[0]);
            exit(0);
        case 'c':
            found_config = 1;
            strcpy(g_configfile , optarg);
            break;
        case 'f':
      g_foregound = 1;
            break;
        case 'l':
            g_log_level = atoi(optarg);
            break;
        default:
            usage(argv[0]);
            exit(-2);
        }
    }
    argc -= optind;
    argv += optind;
    if (argc > 0){
        cmd = argv[0];
        --argc; ++argv;
    }
    if (cmd == ((void *)0)){
        usage(argv[0]);
        exit(-2);
    }
    err = load_conf(&g_conf , g_configfile);
    if (err){
        log_error("read config file %s error!", g_configfile);;
        return -3;
    }
    if (g_log_level < 0)
        g_log_level = g_conf.log_level;
    if ( g_foregound )
        log_init_ex(g_log_level, FCTLOG_SOURCE_PROXY ,
         g_conf.log_file, FCTLOG_TO_CONSOLE|FCTLOG_TO_FILE);
    else
        log_init_ex(g_log_level, FCTLOG_SOURCE_PROXY ,
         g_conf.log_file, FCTLOG_TO_FILE);
    if ( strcasecmp(cmd , "start") == 0){
        if (!g_foregound)
         daemonize();
        printf("pid file: %s\n", g_conf.pid_file);
     err = write_pid(g_conf.pid_file);
     if ( err == 0 ){
        start();
           return 0;
        }else if ( err > 0){
         log_error("forticlient proxy has already run!");;
        }else{
         return -4;
        }
 }
    if ( strcasecmp(cmd , "stop") == 0){
        int pid = get_pid(g_conf.pid_file);
        if (pid > 0){
            log_debug("pid = %d", pid);;
            kill(pid , 15);
        }
    };
    if ( strcasecmp(cmd , "reload") == 0){
        int pid = get_pid(g_conf.pid_file);
        log_debug("pid = %d", pid);;
        kill(pid , 1);
    };
   return 0;
}

canonical_original_code:
int main(int argc, char *argv[]){
    int err = 0; int found_config = 0; int c = 0;
    char *cmd = ((void *)0);
    extern char *optarg;
    extern int optind;
    char *short_options = "hvc:l:f";
    static struct option long_options[] = {
     {"help", 0, ((void *)0), 'h' },
     {"version", 0, ((void *)0), 'v' },
     {"config", 1, ((void *)0), 'c' },
     {"log", 1, ((void *)0), 'l' },
     {"foreground", 0, ((void *)0), 'f' },
     {((void *)0), 0, ((void *)0), 0 }
    };
    memset(&proxies, 0 , sizeof(proxies));
    strcpy(g_configfile , "/etc/forticlient.conf");
    while ((c=getopt_long(argc, argv, short_options,long_options,((void *)0))) != -1){
        switch (c){
        case 'v':
            printf("hproxy  %s\n", "V3.0.0");
            exit(0);
            break;
        case 'h':
            usage(argv[0]);
            exit(0);
        case 'c':
            found_config = 1;
            strcpy(g_configfile , optarg);
            break;
        case 'f':
      g_foregound = 1;
            break;
        case 'l':
            g_log_level = atoi(optarg);
            break;
        default:
            usage(argv[0]);
            exit(-2);
        }
    }
    argc -= optind;
    argv += optind;
    if (argc > 0){
        cmd = argv[0];
        --argc; ++argv;
    }
    if (cmd == ((void *)0)){
        usage(argv[0]);
        exit(-2);
    }
    err = load_conf(&g_conf , g_configfile);
    if (err){
        log_error("read config file %s error!", g_configfile);;
        return -3;
    }
    if (g_log_level < 0)
        g_log_level = g_conf.log_level;
    if ( g_foregound )
        log_init_ex(g_log_level, FCTLOG_SOURCE_PROXY ,
         g_conf.log_file, FCTLOG_TO_CONSOLE|FCTLOG_TO_FILE);
    else
        log_init_ex(g_log_level, FCTLOG_SOURCE_PROXY ,
         g_conf.log_file, FCTLOG_TO_FILE);
    if ( strcasecmp(cmd , "start") == 0){
        if (!g_foregound)
         daemonize();
        printf("pid file: %s\n", g_conf.pid_file);
     err = write_pid(g_conf.pid_file);
     if ( err == 0 ){
        start();
           return 0;
        }else if ( err > 0){
         log_error("forticlient proxy has already run!");;
        }else{
         return -4;
        }
 }
    if ( strcasecmp(cmd , "stop") == 0){
        int pid = get_pid(g_conf.pid_file);
        if (pid > 0){
            log_debug("pid = %d", pid);;
            kill(pid , 15);
        }
    };
    if ( strcasecmp(cmd , "reload") == 0){
        int pid = get_pid(g_conf.pid_file);
        log_debug("pid = %d", pid);;
        kill(pid , 1);
    };
   return 0;
}

variable_types: argc int

variable_types:
argv
char *[]

variable_types: err int

variable_types: c int

variable_types:
cmd
char *

variable_types:
optarg
char *

variable_types: optind int

variable_types: struct option { char *name; int has_arg; int *flag; int val; } []

return_type: int


decompiled_code:
void sig_reload_config()
{
load_conf(g_conf, g_configfile);
log_init(*(unsigned int *)&g_conf[2052], 0LL, (unsigned int)((_DWORD)g_conf + 1024));
pc_kill_all(&proxies, 1LL);
}

canonical_decompiled_code:
void func4()
{
load_conf(g_conf, g_configfile);
log_init(*(unsigned int *)&g_conf[2052], 0LL, (unsigned int)((_DWORD)g_conf + 1024));
pc_kill_all(&proxies, 1LL);
}

original_code:
static void sig_reload_config(int signo){
    load_conf(&g_conf , g_configfile);
    log_init(g_conf.log_level, FCTLOG_SOURCE_PROXY , g_conf.log_file);
   pc_kill_all(&proxies, 1);
}


decompiled_code:
void __fastcall list_del(__int64 a1)
{
_list_del(*(_QWORD **)(a1 + 8), *(_QWORD *)a1);
*(_QWORD *)a1 = 0LL;
*(_QWORD *)(a1 + 8) = 0LL;
}

original_code:
static inline void list_del(struct list_head *entry)
{
 __list_del(entry->prev, entry->next);
 entry->next = ((void *)0);
 entry->prev = ((void *)0);
}

variable_types: struct list_head { struct list_head *next; } *


decompiled_code:
__int64 __fastcall mem_read(__int64 a1, void *a2, int a3)
{
int v3; // eax
unsigned int v4; // ebx

v3 = *(_DWORD *)(a1 + 36);
v4 = *(_DWORD *)(a1 + 32) - v3;
if ( v4 )
{
if ( (int)v4 > a3 )
v4 = a3;
memcpy(a2, (const void *)(a1 + v3 + 40), (int)v4);
*(_DWORD *)(a1 + 36) += v4;
}
return v4;
}

canonical_decompiled_code:
__int64 __fastcall func5(__int64 a1, void *a2, int a3)
{
int v3; // eax
unsigned int v4; // ebx

v3 = *(_DWORD *)(a1 + 36);
v4 = *(_DWORD *)(a1 + 32) - v3;
if ( v4 )
{
if ( (int)v4 > a3 )
v4 = a3;
memcpy(a2, (const void *)(a1 + v3 + 40), (int)v4);
*(_DWORD *)(a1 + 36) += v4;
}
return v4;
}

original_code:
static int mem_read(struct common_cache_t* cache,char* buf, int buflen){
    int real_count = 0;
    struct mem_cache_t* mcache = (struct mem_cache_t*)cache;
    int left = mcache->mem_len - mcache->read_count;
    if (left == 0) return 0;
    real_count = left > buflen?buflen: left;
    memcpy(buf , mcache->mem + mcache->read_count, real_count);
    mcache->read_count += real_count;
    return real_count;
}

canonical_original_code:
static int mem_read(struct common_cache_t *cache, char *buf, int buflen){
    int real_count = 0;
    struct mem_cache_t *mcache = (struct mem_cache_t*)cache;
    int left = mcache->mem_len - mcache->read_count;
    if (left == 0) return 0;
    real_count = left > buflen?buflen: left;
    memcpy(buf , mcache->mem + mcache->read_count, real_count);
    mcache->read_count += real_count;
    return real_count;
}

variable_types: struct common_cache_t { struct list_head { struct list_head *next; } list; int (*read)(struct common_cache_t *, char *, int); void (*destroy)(struct common_cache_t *); } *

variable_types:
buf
char *

variable_types: buflen int

variable_types: struct mem_cache_t { struct common_cache_t { struct list_head { struct list_head *next; } list; int (*read)(struct common_cache_t *, char *, int); void (*destroy)(struct common_cache_t *); } cache; int mem_len; int read_count; char mem[]; } *

variable_types: left int

user_defined_types: struct common_cache_t { struct list_head list; int (*read)(struct common_cache_t *, char *, int); void (*destroy)(struct common_cache_t *); }

user_defined_types: struct mem_cache_t { struct common_cache_t cache; int mem_len; int read_count; char mem[]; }


decompiled_code:
void __fastcall mem_destroy(void *a1)
{
if ( a1 )
free(a1);
}

canonical_decompiled_code:
void __fastcall func6(void *a1)
{
if ( a1 )
free(a1);
}

original_code:
static void mem_destroy(struct common_cache_t* cache){
    if (cache != ((void *)0))
        free(cache);
}

canonical_original_code:
static void mem_destroy(struct common_cache_t *cache){
    if (cache != ((void *)0))
        free(cache);
}

user_defined_types: struct list_head { struct list_head *next; }


decompiled_code:
void __fastcall file_destroy(void *ptr)
{
if ( ptr )
{
if ( *((int *)ptr + 8) > 0 )
{
while ( close(*((_DWORD *)ptr + 8)) == -1 && *_errno_location() == 4 )
;
}
*((_DWORD *)ptr + 8) = -1;
unlink((const char *)ptr + 36);
free(ptr);
}
}

canonical_decompiled_code:
void __fastcall func7(void *ptr)
{
if ( ptr )
{
if ( *((int *)ptr + 8) > 0 )
{
while ( close(*((_DWORD *)ptr + 8)) == -1 && *_errno_location() == 4 )
;
}
*((_DWORD *)ptr + 8) = -1;
unlink((const char *)ptr + 36);
free(ptr);
}
}

original_code:
static void file_destroy(struct common_cache_t* cache){
    if (cache == ((void *)0)) return ;
    struct file_cache_t* fcache = (struct file_cache_t*)cache;
    if (fcache->fd > 0) {while (close(fcache->fd) == -1 && (*__errno_location ()) == 4);};
    fcache->fd = -1;
    unlink(fcache->file_name);
    free(cache);
}

canonical_original_code:
static void file_destroy(struct common_cache_t *cache){
    if (cache == ((void *)0)) return ;
    struct file_cache_t *fcache = (struct file_cache_t*)cache;
    if (fcache->fd > 0) {while (close(fcache->fd) == -1 && (*__errno_location ()) == 4);};
    fcache->fd = -1;
    unlink(fcache->file_name);
    free(cache);
}

variable_types: struct file_cache_t { struct common_cache_t { struct list_head { struct list_head *next; } list; int (*read)(struct common_cache_t *, char *, int); void (*destroy)(struct common_cache_t *); } cache; int fd; char file_name[512]; } *

user_defined_types: struct file_cache_t { struct common_cache_t cache; int fd; char file_name[512]; }


decompiled_code:
__int64 __fastcall file_read(__int64 a1, void *a2, unsigned int a3)
{
int v4; // ebx

if ( a1 )
{
v4 = 0;
if ( *(int *)(a1 + 32) >= 0 )
{
do
v4 = read(*(_DWORD *)(a1 + 32), a2, a3);
while ( v4 < 0 && *_errno_location() == 4 );
}
}
else
{
v4 = 0;
}
return (unsigned int)v4;
}

canonical_decompiled_code:
__int64 __fastcall func8(__int64 a1, void *a2, unsigned int a3)
{
int v4; // ebx

if ( a1 )
{
v4 = 0;
if ( *(int *)(a1 + 32) >= 0 )
{
do
v4 = read(*(_DWORD *)(a1 + 32), a2, a3);
while ( v4 < 0 && *_errno_location() == 4 );
}
}
else
{
v4 = 0;
}
return (unsigned int)v4;
}

original_code:
static int file_read(struct common_cache_t* cache,char* buf, int buflen){
    if (cache == ((void *)0)) return 0;
    struct file_cache_t* fcache = (struct file_cache_t*)cache;
    if (fcache->fd < 0) return 0;
    int n = 0;
    do {
        n = read(fcache->fd, buf , buflen);
    } while ( n < 0 && (*__errno_location ()) == 4);
    return n;
}

canonical_original_code:
static int file_read(struct common_cache_t *cache, char *buf, int buflen){
    if (cache == ((void *)0)) return 0;
    struct file_cache_t *fcache = (struct file_cache_t*)cache;
    if (fcache->fd < 0) return 0;
    int n = 0;
    do {
        n = read(fcache->fd, buf , buflen);
    } while ( n < 0 && (*__errno_location ()) == 4);
    return n;
}

variable_types: n int


decompiled_code:
__int64 __fastcall cp_init(__int64 a1)
{
__int64 result; // rax

*(_DWORD *)a1 = 0;
result = a1 + 8;
*(_QWORD *)(a1 + 8) = a1 + 8;
*(_QWORD *)(a1 + 16) = a1 + 8;
return result;
}

canonical_decompiled_code:
__int64 __fastcall func9(__int64 a1)
{
__int64 result; // rax

*(_DWORD *)a1 = 0;
result = a1 + 8;
*(_QWORD *)(a1 + 8) = a1 + 8;
*(_QWORD *)(a1 + 16) = a1 + 8;
return result;
}

original_code:
void cp_init(struct cache_pool_t* cp){
    cp->cache_count = 0;
    do { (&cp->cache_head)->next = (&cp->cache_head); (&cp->cache_head)->prev = (&cp->cache_head); } while (0);
}

canonical_original_code:
void cp_init(struct cache_pool_t *cp){
    cp->cache_count = 0;
    do { (&cp->cache_head)->next = (&cp->cache_head); (&cp->cache_head)->prev = (&cp->cache_head); } while (0);
}

variable_types: struct cache_pool_t { int cache_count; struct list_head { struct list_head *next; } cache_head; } *

user_defined_types: struct cache_pool_t { int cache_count; struct list_head cache_head; }


decompiled_code:
_BOOL8 __fastcall cp_is_empty(_DWORD *a1)
{
return *a1 <= 0;
}

canonical_decompiled_code:
_BOOL8 __fastcall func11(_DWORD *a1)
{
return *a1 <= 0;
}

original_code:
int cp_is_empty(struct cache_pool_t* cp){
    return (cp->cache_count > 0)? 0 : 1;
}

canonical_original_code:
int cp_is_empty(struct cache_pool_t *cp){
    return (cp->cache_count > 0)? 0 : 1;
}


decompiled_code:
__int64 __fastcall cp_read(unsigned int *a1, __int64 a2, unsigned int a3)
{
__int64 result; // rax
__int64 v5; // rbx
bool v6; // zf

result = *a1;
if ( (_DWORD)result )
{
while ( 1 )
{
v5 = *((_QWORD *)a1 + 1);
if ( (unsigned int *)v5 == a1 + 2 )
break;
result = (*(__int64 (__fastcall **)(_QWORD, __int64, _QWORD))(v5 + 16))(*((_QWORD *)a1 + 1), a2, a3);
if ( (int)result <= 0 )
{
list_del(v5);
(*(void (__fastcall **)(__int64))(v5 + 24))(v5);
v6 = *a1 == 1;
result = *a1 - 1;
*a1 = result;
if ( !v6 )
continue;
}
return result;
}
result = 0LL;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func12(unsigned int *a1, __int64 a2, unsigned int a3)
{
__int64 result; // rax
__int64 v5; // rbx
bool v6; // zf

result = *a1;
if ( (_DWORD)result )
{
while ( 1 )
{
v5 = *((_QWORD *)a1 + 1);
if ( (unsigned int *)v5 == a1 + 2 )
break;
result = (*(__int64 (__fastcall **)(_QWORD, __int64, _QWORD))(v5 + 16))(*((_QWORD *)a1 + 1), a2, a3);
if ( (int)result <= 0 )
{
func3(v5);
(*(void (__fastcall **)(__int64))(v5 + 24))(v5);
v6 = *a1 == 1;
result = *a1 - 1;
*a1 = result;
if ( !v6 )
continue;
}
return result;
}
result = 0LL;
}
return result;
}

original_code:
int cp_read(struct cache_pool_t* cp ,char* buf, int buflen){
    for(;;){
        if (cp->cache_count == 0)
            return 0;
        struct common_cache_t* cur_cache =
            (struct common_cache_t*)cp->cache_head.next;
        if ((unsigned long)cur_cache == (unsigned long)(&cp->cache_head))
            return 0;
        int n = cur_cache->read(cur_cache , buf , buflen);
        if (n <= 0){
            list_del(&cur_cache->list);
            cur_cache->destroy(cur_cache);
            cp->cache_count--;
        }else
            return n;
    }
    return 0;
}

canonical_original_code:
int cp_read(struct cache_pool_t *cp, char *buf, int buflen){
    for(;;){
        if (cp->cache_count == 0)
            return 0;
        struct common_cache_t *cur_cache = (struct common_cache_t*)cp->cache_head.next;
        if ((unsigned long)cur_cache == (unsigned long)(&cp->cache_head))
            return 0;
        int n = cur_cache->read(cur_cache , buf , buflen);
        if (n <= 0){
            list_del(&cur_cache->list);
            cur_cache->destroy(cur_cache);
            cp->cache_count--;
        }else
            return n;
    }
    return 0;
}


original_code:
void cp_destroy(struct cache_pool_t* cp){
    struct list_head *pos = ((void *)0);
    struct common_cache_t* cur_cache = ((void *)0);
    if (cp == ((void *)0) || cp->cache_count == 0) return;
    for (pos = (&cp->cache_head)->next; pos != (&cp->cache_head); pos = pos->next){
        cur_cache = (struct common_cache_t*)pos;
        pos = pos->prev;
        list_del(&cur_cache->list);
        cur_cache->destroy(cur_cache);
    }
    cp->cache_count = 0;
}

canonical_original_code:
void cp_destroy(struct cache_pool_t *cp){
    struct list_head *pos = ((void *)0);
    struct common_cache_t *cur_cache = ((void *)0);
    if (cp == ((void *)0) || cp->cache_count == 0) return;
    for (pos = (&cp->cache_head)->next; pos != (&cp->cache_head); pos = pos->next){
        cur_cache = (struct common_cache_t *)pos;
        pos = pos->prev;
        list_del(&cur_cache->list);
        cur_cache->destroy(cur_cache);
    }
    cp->cache_count = 0;
}


decompiled_code:
_BOOL8 __fastcall session_is_closed(_DWORD *a1)
{
_BOOL8 result; // rax
time_t v2; // rdx

if ( a1 )
{
result = 1LL;
if ( *((_QWORD *)a1 + 8471) != 0x400000004LL )
{
if ( a1[16943] != 4 && a1[16942] != 4 || (v2 = time(0LL) - (int)a1[16952], result = 1LL, v2 <= 59) )
{
if ( a1[16943] == 3 || (result = 0LL, a1[16942] == 3) )
result = time(0LL) - (int)a1[16952] > 59;
}
}
}
else
{
log_error("session can not be NULL!");
result = 0LL;
}
return result;
}

original_code:
static int session_is_closed(struct fctl_session_t* session){
    if (session == ((void *)0)){
        log_error("session can not be NULL!");;
        return 0;
    }
    if (session->local_status == SESSION_CLOSED
        && session->remote_status == SESSION_CLOSED){
        return 1;
    }
    if ((session->local_status == SESSION_CLOSED
           || session->remote_status == SESSION_CLOSED)
        && ( (time(0) - session->closing_time) >= 60)
       )
       return 1;
    if ( (session->local_status == SESSION_CLOSING
           || session->remote_status == SESSION_CLOSING)
        && ( (time(0) - session->closing_time) >= 60)
       )
       return 1;
    return 0;
}

canonical_original_code:
static int session_is_closed(struct fctl_session_t *session){
    if (session == ((void *)0)){
        log_error("session can not be NULL!");;
        return 0;
    }
    if (session->local_status == SESSION_CLOSED
        && session->remote_status == SESSION_CLOSED){
        return 1;
    }
    if ((session->local_status == SESSION_CLOSED
           || session->remote_status == SESSION_CLOSED)
        && ( (time(0) - session->closing_time) >= 60)
       )
       return 1;
    if ( (session->local_status == SESSION_CLOSING
           || session->remote_status == SESSION_CLOSING)
        && ( (time(0) - session->closing_time) >= 60)
       )
       return 1;
    return 0;
}

variable_types: struct fctl_session_t { struct list_head { struct list_head *next; } list; struct fctl_proxy_t { int daemon; int port; int pid; struct fctl_proto_t { char proto_name[20]; int port; enum PROXY_TYPE { PROXY_SYN=0, PROXY_ASY=1 } proxy_type; int (*on_local_rev)(struct fctl_session_t *, char *, int); int (*on_remote_rev)(struct fctl_session_t *, char *, int); int (*on_connect)(struct fctl_session_t *); int (*on_disconnect)(struct fctl_session_t *); int (*on_notification)(struct fctl_session_t *, struct event_header_t { int session_id; int event_type; int event_len; } *); } *proto; int valid_port; int max_bind_port; int min_bind_port; char proto_name[20]; unsigned int cur_session_id; struct list_head session_head; int (*run)(struct fctl_proxy_t *); int (*get_port)(struct fctl_proxy_t *); int (*read)(int, char *, int); int (*write)(int, char *, int); int (*listen)(struct fctl_proxy_t *); int (*local_send)(struct fctl_proxy_t *, struct fctl_session_t *); int (*remote_send)(struct fctl_proxy_t *, struct fctl_session_t *); int (*local_close)(struct fctl_proxy_t *, struct fctl_session_t *); int (*remote_close)(struct fctl_proxy_t *, struct fctl_session_t *); int (*remote_connect)(struct fctl_proxy_t *, struct fctl_session_t *, char *, int); } *proxy; int local_fd; int remote_fd; struct sockaddr_in { unsigned short sin_family; unsigned short sin_port; struct in_addr { unsigned int s_addr; } sin_addr; unsigned char sin_zero[-1]; } local_addr; int remote_src_port; int remote_dst_port; struct sockaddr_in remote_addr; struct rwbuff_t { char buf[-1]; char *readp; char *writep; char *sendp; int buf_len; int buf_default_len; struct cache_pool_t { int cache_count; struct list_head cache_head; } cache_pool; } local_buf; struct rwbuff_t remote_buf; int remote_status; int local_status; int proto_status; int local_retry_times; int remote_retry_times; void *private_data; long create_time; int closing_time; struct fctl_spool_t { int fd; char name[512]; int size; int exists; } spool; int session_id; int (*on_local_recv)(struct fctl_session_t *); int (*on_remote_recv)(struct fctl_session_t *); int (*on_local_send)(struct fctl_session_t *); int (*on_remote_send)(struct fctl_session_t *); int (*on_local_close)(struct fctl_session_t *); int (*on_local_connect)(struct fctl_session_t *); int (*on_remote_close)(struct fctl_session_t *); int (*on_remote_connect)(struct fctl_session_t *); int (*is_closed)(struct fctl_session_t *); int (*close)(struct fctl_session_t *); int (*free)(struct fctl_session_t *); } *


decompiled_code:
__int64 __fastcall session_close(int *a1)
{
__int64 result; // rax

if ( a1 )
{
if ( a1[7] > 0 )
{
while ( close(a1[7]) == -1 && *_errno_location() == 4 )
;
}
if ( a1[6] > 0 )
{
while ( close(a1[6]) == -1 && *_errno_location() == 4 )
;
}
a1[7] = -1;
a1[6] = -1;
cp_destroy(a1 + 16936);
cp_destroy(a1 + 8474);
a1[16943] = 4;
a1[16942] = 4;
result = 0LL;
}
else
{
log_error("session can not be NULL!");
result = 0xFFFFFFFFLL;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func1(int *a1)
{
__int64 result; // rax

if ( a1 )
{
if ( a1[7] > 0 )
{
while ( close(a1[7]) == -1 && *_errno_location() == 4 )
;
}
if ( a1[6] > 0 )
{
while ( close(a1[6]) == -1 && *_errno_location() == 4 )
;
}
a1[7] = -1;
a1[6] = -1;
cp_destroy(a1 + 16936);
cp_destroy(a1 + 8474);
a1[16943] = 4;
a1[16942] = 4;
result = 0LL;
}
else
{
log_error("session can not be NULL!");
result = 0xFFFFFFFFLL;
}
return result;
}

original_code:
static int session_close(struct fctl_session_t* session){
    if (session == ((void *)0)){
        log_error("session can not be NULL!");;
        return -1;
    }
     if (session->remote_fd > 0) {while (close(session->remote_fd) == -1 && (*__errno_location ()) == 4);} ;
     if (session->local_fd > 0) {while (close(session->local_fd) == -1 && (*__errno_location ()) == 4);} ;
     session->remote_fd = -1;
     session->local_fd = -1;
     cp_destroy(&session->remote_buf.cache_pool);
     cp_destroy(&session->local_buf.cache_pool);
     session->local_status = SESSION_CLOSED;
     session->remote_status = SESSION_CLOSED;
    return 0;
}

canonical_original_code:
static int session_close(struct fctl_session_t *session){
    if (session == ((void *)0)){
        log_error("session can not be NULL!");;
        return -1;
    }
     if (session->remote_fd > 0) {while (close(session->remote_fd) == -1 && (*__errno_location ()) == 4);} ;
     if (session->local_fd > 0) {while (close(session->local_fd) == -1 && (*__errno_location ()) == 4);} ;
     session->remote_fd = -1;
     session->local_fd = -1;
     cp_destroy(&session->remote_buf.cache_pool);
     cp_destroy(&session->local_buf.cache_pool);
     session->local_status = SESSION_CLOSED;
     session->remote_status = SESSION_CLOSED;
    return 0;
}

user_defined_types: struct fctl_spool_t { int fd; char name[512]; int size; int exists; }

user_defined_types: enum PROXY_TYPE { PROXY_SYN=0, PROXY_ASY=1 }

user_defined_types: struct event_header_t { int session_id; int event_type; int event_len; }


decompiled_code:
__int64 __fastcall session_check_remote_extra_data(__int64 a1)
{
__int64 v1; // rbp
__int64 result; // rax
__int64 v3; // r12
unsigned int v4; // ebx

v1 = a1 + 33920;
result = rwbuff_get_sendn(a1 + 33920);
if ( !(_DWORD)result )
{
result = rwbuff_get_readn(v1);
if ( !(_DWORD)result )
{
result = cp_is_empty(a1 + 67744);
if ( !(_DWORD)result )
{
v3 = rwbuff_get_writep(v1);
result = rwbuff_get_writen(v1);
if ( (_DWORD)result )
{
result = cp_read(a1 + 67744, v3, (unsigned int)result);
v4 = result;
if ( (int)result > 0 )
{
rwbuff_write(v1, (unsigned int)result);
result = rwbuff_read(v1, v4);
}
}
}
}
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func2(__int64 a1)
{
__int64 v1; // rbp
__int64 result; // rax
__int64 v3; // r12
unsigned int v4; // ebx

v1 = a1 + 33920;
result = rwbuff_get_sendn(a1 + 33920);
if ( !(_DWORD)result )
{
result = rwbuff_get_readn(v1);
if ( !(_DWORD)result )
{
result = cp_is_empty(a1 + 67744);
if ( !(_DWORD)result )
{
v3 = rwbuff_get_writep(v1);
result = rwbuff_get_writen(v1);
if ( (_DWORD)result )
{
result = cp_read(a1 + 67744, v3, (unsigned int)result);
v4 = result;
if ( (int)result > 0 )
{
rwbuff_write(v1, (unsigned int)result);
result = rwbuff_read(v1, v4);
}
}
}
}
}
return result;
}

original_code:
static void session_check_remote_extra_data(struct fctl_session_t* session){
    if (rwbuff_get_sendn(&session->remote_buf) != 0
        || rwbuff_get_readn(&session->remote_buf)!= 0) return;
    if (cp_is_empty(&session->remote_buf.cache_pool) ) return;
    char * buf = rwbuff_get_writep(&session->remote_buf);
    int space = rwbuff_get_writen(&session->remote_buf);
    if ( space == 0) {
        return ;
    }
    int n = cp_read(&session->remote_buf.cache_pool, buf , space);
    if (n > 0){
        rwbuff_write(&session->remote_buf , n);
        rwbuff_read(&session->remote_buf, n);
    }
}

canonical_original_code:
static void session_check_remote_extra_data(struct fctl_session_t *session){
    if (rwbuff_get_sendn(&session->remote_buf) != 0
        || rwbuff_get_readn(&session->remote_buf)!= 0) return;
    if (cp_is_empty(&session->remote_buf.cache_pool) ) return;
    char *buf = rwbuff_get_writep(&session->remote_buf);
    int space = rwbuff_get_writen(&session->remote_buf);
    if ( space == 0) {
        return ;
    }
    int n = cp_read(&session->remote_buf.cache_pool, buf , space);
    if (n > 0){
        rwbuff_write(&session->remote_buf , n);
        rwbuff_read(&session->remote_buf, n);
    }
}

variable_types: space int


decompiled_code:
__int64 __fastcall session_on_remote_send(__int64 a1)
{
__int64 v2; // r13
__int64 v3; // r12
int v4; // eax
unsigned int v5; // ebx
int v6; // edi
__int64 result; // rax
char *v8; // rax

if ( a1 && *(_QWORD *)(a1 + 16) )
{
session_check_remote_extra_data(a1);
v2 = rwbuff_get_sendp(a1 + 33920);
v3 = (unsigned int)rwbuff_get_sendn(a1 + 33920);
log_debug("%d data in remote buffer need to be sent!", v3);
if ( (_DWORD)v3 )
{
do
{
v4 = (*(__int64 (__fastcall **)(_QWORD, __int64, _QWORD))(*(_QWORD *)(a1 + 16) + 104LL))(
*(unsigned int *)(a1 + 24),
v2,
(unsigned int)v3);
v5 = v4;
if ( v4 > 0 )
{
log_debug(" %d data in remote buffer are sent successfully.", (unsigned int)v4);
*(_DWORD *)(a1 + 67808) = time(0LL);
rwbuff_send(a1 + 33920, v5);
session_check_remote_extra_data(a1);
goto LABEL_13;
}
v6 = *_errno_location();
}
while ( v6 == 4 );
if ( v6 == 11 )
{
result = 1LL;
}
else
{
v8 = strerror(v6);
log_error("write error:%s", v8);
result = 4294967294LL;
}
}
else
{
log_debug("no data in remote buffer need to be sent");
LABEL_13:
result = rwbuff_get_sendn(a1 + 33920);
if ( (_DWORD)result )
{
result = 0LL;
}
else if ( *(_DWORD *)(a1 + 67768) == 3 )
{
*(_DWORD *)(a1 + 67768) = 4;
}
}
}
else
{
log_error("session can not be NULL!");
result = 0xFFFFFFFFLL;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func3(__int64 a1)
{
__int64 v2; // r13
__int64 v3; // r12
int v4; // eax
unsigned int v5; // ebx
int v6; // edi
__int64 result; // rax
char *v8; // rax

if ( a1 && *(_QWORD *)(a1 + 16) )
{
func2(a1);
v2 = rwbuff_get_sendp(a1 + 33920);
v3 = (unsigned int)rwbuff_get_sendn(a1 + 33920);
log_debug("%d data in remote buffer need to be sent!", v3);
if ( (_DWORD)v3 )
{
do
{
v4 = (*(__int64 (__fastcall **)(_QWORD, __int64, _QWORD))(*(_QWORD *)(a1 + 16) + 104LL))(
*(unsigned int *)(a1 + 24),
v2,
(unsigned int)v3);
v5 = v4;
if ( v4 > 0 )
{
log_debug(" %d data in remote buffer are sent successfully.", (unsigned int)v4);
*(_DWORD *)(a1 + 67808) = time(0LL);
rwbuff_send(a1 + 33920, v5);
func2(a1);
goto LABEL_13;
}
v6 = *_errno_location();
}
while ( v6 == 4 );
if ( v6 == 11 )
{
result = 1LL;
}
else
{
v8 = strerror(v6);
log_error("write error:%s", v8);
result = 4294967294LL;
}
}
else
{
log_debug("no data in remote buffer need to be sent");
LABEL_13:
result = rwbuff_get_sendn(a1 + 33920);
if ( (_DWORD)result )
{
result = 0LL;
}
else if ( *(_DWORD *)(a1 + 67768) == 3 )
{
*(_DWORD *)(a1 + 67768) = 4;
}
}
}
else
{
log_error("session can not be NULL!");
result = 0xFFFFFFFFLL;
}
return result;
}

original_code:
static int session_on_remote_send(struct fctl_session_t* session){
    if (session == ((void *)0) || session->proxy == ((void *)0)){
        log_error("session can not be NULL!");;
        return -1;
    }
    session_check_remote_extra_data(session);
    char* buf = rwbuff_get_sendp(&session->remote_buf);
    int space = rwbuff_get_sendn(&session->remote_buf);
    log_debug("%d data in remote buffer need to be sent!", space);;
    if ( space == 0){
        log_debug("no data in remote buffer need to be sent");;
        goto ret;
    }
    int n;
again:
    n = session->proxy->write(session->local_fd, buf , space);
    if (n <= 0) {
        if ( (*__errno_location ()) == 4) goto again;
        if ( (*__errno_location ()) != 11){
            log_error("write error:%s",strerror((*__errno_location ())));;
            return -2;
        }
        return 1;
    }
    log_debug(" %d data in remote buffer are sent successfully.", n);;
     session->closing_time = time(0);
    rwbuff_send(&session->remote_buf, n);
    session_check_remote_extra_data(session);
ret :
     if ( rwbuff_get_sendn(&session->remote_buf) == 0
        && session->remote_status == SESSION_CLOSING) {
        session->remote_status = SESSION_CLOSED;
    }
    return 0;
}

canonical_original_code:
static int session_on_remote_send(struct fctl_session_t *session){
    if (session == ((void *)0) || session->proxy == ((void *)0)){
        log_error("session can not be NULL!");;
        return -1;
    }
    session_check_remote_extra_data(session);
    char *buf = rwbuff_get_sendp(&session->remote_buf);
    int space = rwbuff_get_sendn(&session->remote_buf);
    log_debug("%d data in remote buffer need to be sent!", space);;
    if ( space == 0){
        log_debug("no data in remote buffer need to be sent");;
        goto ret;
    }
    int n;
again:
    n = session->proxy->write(session->local_fd, buf , space);
    if (n <= 0) {
        if ( (*__errno_location ()) == 4) goto again;
        if ( (*__errno_location ()) != 11){
            log_error("write error:%s",strerror((*__errno_location ())));;
            return -2;
        }
        return 1;
    }
    log_debug(" %d data in remote buffer are sent successfully.", n);;
     session->closing_time = time(0);
    rwbuff_send(&session->remote_buf, n);
    session_check_remote_extra_data(session);
ret :
     if ( rwbuff_get_sendn(&session->remote_buf) == 0
        && session->remote_status == SESSION_CLOSING) {
        session->remote_status = SESSION_CLOSED;
    }
    return 0;
}


decompiled_code:
__int64 __fastcall session_check_local_extra_data(__int64 a1)
{
__int64 v1; // rbp
__int64 result; // rax
__int64 v3; // r12
unsigned int v4; // ebx

v1 = a1 + 72;
result = rwbuff_get_sendn(a1 + 72);
if ( !(_DWORD)result )
{
result = rwbuff_get_readn(v1);
if ( !(_DWORD)result )
{
result = cp_is_empty(a1 + 33896);
if ( !(_DWORD)result )
{
v3 = rwbuff_get_writep(v1);
result = rwbuff_get_writen(v1);
if ( (_DWORD)result )
{
result = cp_read(a1 + 33896, v3, (unsigned int)result);
v4 = result;
if ( (int)result > 0 )
{
rwbuff_write(v1, (unsigned int)result);
result = rwbuff_read(v1, v4);
}
}
}
}
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func4(__int64 a1)
{
__int64 v1; // rbp
__int64 result; // rax
__int64 v3; // r12
unsigned int v4; // ebx

v1 = a1 + 72;
result = rwbuff_get_sendn(a1 + 72);
if ( !(_DWORD)result )
{
result = rwbuff_get_readn(v1);
if ( !(_DWORD)result )
{
result = cp_is_empty(a1 + 33896);
if ( !(_DWORD)result )
{
v3 = rwbuff_get_writep(v1);
result = rwbuff_get_writen(v1);
if ( (_DWORD)result )
{
result = cp_read(a1 + 33896, v3, (unsigned int)result);
v4 = result;
if ( (int)result > 0 )
{
rwbuff_write(v1, (unsigned int)result);
result = rwbuff_read(v1, v4);
}
}
}
}
}
return result;
}

original_code:
static void session_check_local_extra_data(struct fctl_session_t* session){
    if (rwbuff_get_sendn(&session->local_buf) != 0
        || rwbuff_get_readn(&session->local_buf)!= 0) return;
    if (cp_is_empty(&session->local_buf.cache_pool) ) return;
    char * buf = rwbuff_get_writep(&session->local_buf);
    int space = rwbuff_get_writen(&session->local_buf);
    if ( space == 0) {
        return ;
    }
    int n = cp_read(&session->local_buf.cache_pool, buf , space);
    if (n > 0){
        rwbuff_write(&session->local_buf , n);
        rwbuff_read(&session->local_buf, n);
    }
}

canonical_original_code:
static void session_check_local_extra_data(struct fctl_session_t *session){
    if (rwbuff_get_sendn(&session->local_buf) != 0
        || rwbuff_get_readn(&session->local_buf)!= 0) return;
    if (cp_is_empty(&session->local_buf.cache_pool) ) return;
    char *buf = rwbuff_get_writep(&session->local_buf);
    int space = rwbuff_get_writen(&session->local_buf);
    if ( space == 0) {
        return ;
    }
    int n = cp_read(&session->local_buf.cache_pool, buf , space);
    if (n > 0){
        rwbuff_write(&session->local_buf , n);
        rwbuff_read(&session->local_buf, n);
    }
}


decompiled_code:
__int64 __fastcall session_on_local_send(__int64 a1)
{
__int64 result; // rax
__int64 v3; // r13
unsigned int v4; // eax
unsigned int v5; // er12
int v6; // ebp
int v7; // edi
char *v8; // rax

if ( a1 && *(_QWORD *)(a1 + 16) )
{
result = 0LL;
if ( *(_DWORD *)(a1 + 67768) == 2 )
{
session_check_local_extra_data(a1);
v3 = rwbuff_get_sendp(a1 + 72);
v4 = rwbuff_get_sendn(a1 + 72);
v5 = v4;
if ( v4 )
{
log_debug("%d data in local buffer need to be sent!", v4);
do
{
v6 = (*(__int64 (__fastcall **)(_QWORD, __int64, _QWORD))(*(_QWORD *)(a1 + 16) + 104LL))(
*(unsigned int *)(a1 + 28),
v3,
v5);
if ( v6 > 0 )
{
*(_DWORD *)(a1 + 67808) = time(0LL);
log_debug(" %d data in local buffer are sent successfully.", (unsigned int)v6);
rwbuff_send(a1 + 72, (unsigned int)v6);
session_check_local_extra_data(a1);
goto LABEL_13;
}
v7 = *_errno_location();
}
while ( v7 == 4 );
if ( v7 == 11 )
{
result = 1LL;
}
else
{
v8 = strerror(v7);
log_error("write error:%s", v8);
result = 4294967294LL;
}
}
else
{
log_debug("no data in local buffer need to be sent");
LABEL_13:
result = rwbuff_get_sendn(a1 + 72);
if ( (_DWORD)result )
{
result = 0LL;
}
else if ( *(_DWORD *)(a1 + 67772) == 3 )
{
*(_DWORD *)(a1 + 67772) = 4;
}
}
}
}
else
{
log_error("session can not be NULL!");
result = 0xFFFFFFFFLL;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func5(__int64 a1)
{
__int64 result; // rax
__int64 v3; // r13
unsigned int v4; // eax
unsigned int v5; // er12
int v6; // ebp
int v7; // edi
char *v8; // rax

if ( a1 && *(_QWORD *)(a1 + 16) )
{
result = 0LL;
if ( *(_DWORD *)(a1 + 67768) == 2 )
{
func4(a1);
v3 = rwbuff_get_sendp(a1 + 72);
v4 = rwbuff_get_sendn(a1 + 72);
v5 = v4;
if ( v4 )
{
log_debug("%d data in local buffer need to be sent!", v4);
do
{
v6 = (*(__int64 (__fastcall **)(_QWORD, __int64, _QWORD))(*(_QWORD *)(a1 + 16) + 104LL))(
*(unsigned int *)(a1 + 28),
v3,
v5);
if ( v6 > 0 )
{
*(_DWORD *)(a1 + 67808) = time(0LL);
log_debug(" %d data in local buffer are sent successfully.", (unsigned int)v6);
rwbuff_send(a1 + 72, (unsigned int)v6);
func4(a1);
goto LABEL_13;
}
v7 = *_errno_location();
}
while ( v7 == 4 );
if ( v7 == 11 )
{
result = 1LL;
}
else
{
v8 = strerror(v7);
log_error("write error:%s", v8);
result = 4294967294LL;
}
}
else
{
log_debug("no data in local buffer need to be sent");
LABEL_13:
result = rwbuff_get_sendn(a1 + 72);
if ( (_DWORD)result )
{
result = 0LL;
}
else if ( *(_DWORD *)(a1 + 67772) == 3 )
{
*(_DWORD *)(a1 + 67772) = 4;
}
}
}
}
else
{
log_error("session can not be NULL!");
result = 0xFFFFFFFFLL;
}
return result;
}

original_code:
static int session_on_local_send(struct fctl_session_t* session){
     if (session == ((void *)0) || session->proxy == ((void *)0)){
        log_error("session can not be NULL!");;
        return -1;
    }
    if (session->remote_status != SESSION_CONNECTED)
        return 0;
    session_check_local_extra_data(session);
    char* local_buf = rwbuff_get_sendp(&session->local_buf);
    int space = rwbuff_get_sendn(&session->local_buf);
    if ( space == 0){
        log_debug("no data in local buffer need to be sent");;
        goto ret;
    }
    log_debug("%d data in local buffer need to be sent!", space);;
    int n;
again:
    n = session->proxy->write(session->remote_fd, local_buf , space);
    if (n <= 0) {
        if ( (*__errno_location ()) == 4) goto again;
        if ( (*__errno_location ()) != 11 ){
            log_error("write error:%s",strerror((*__errno_location ())));;
            return -2;
        }
        return 1;
    }
    session->closing_time = time(0);
    log_debug(" %d data in local buffer are sent successfully.", n);;
    rwbuff_send(&session->local_buf, n);
    session_check_local_extra_data(session);
ret:
    if ( rwbuff_get_sendn(&session->local_buf) == 0
        && session->local_status == SESSION_CLOSING) {
        session->local_status = SESSION_CLOSED;
    }
    return 0;
}

canonical_original_code:
static int session_on_local_send(struct fctl_session_t *session){
     if (session == ((void *)0) || session->proxy == ((void *)0)){
        log_error("session can not be NULL!");;
        return -1;
    }
    if (session->remote_status != SESSION_CONNECTED)
        return 0;
    session_check_local_extra_data(session);
    char *local_buf = rwbuff_get_sendp(&session->local_buf);
    int space = rwbuff_get_sendn(&session->local_buf);
    if ( space == 0){
        log_debug("no data in local buffer need to be sent");;
        goto ret;
    }
    log_debug("%d data in local buffer need to be sent!", space);;
    int n;
again:
    n = session->proxy->write(session->remote_fd, local_buf , space);
    if (n <= 0) {
        if ( (*__errno_location ()) == 4) goto again;
        if ( (*__errno_location ()) != 11 ){
            log_error("write error:%s",strerror((*__errno_location ())));;
            return -2;
        }
        return 1;
    }
    session->closing_time = time(0);
    log_debug(" %d data in local buffer are sent successfully.", n);;
    rwbuff_send(&session->local_buf, n);
    session_check_local_extra_data(session);
ret:
    if ( rwbuff_get_sendn(&session->local_buf) == 0
        && session->local_status == SESSION_CLOSING) {
        session->local_status = SESSION_CLOSED;
    }
    return 0;
}


decompiled_code:
__int64 __fastcall session_on_remote_recv(__int64 a1)
{
__int64 v2; // r14
__int64 v3; // r13
__int64 v4; // r12
int v5; // eax
unsigned int v6; // ebx
int v7; // edi
char *v9; // rax
__int64 v10; // rbx
unsigned int v11; // eax

if ( a1 && *(_QWORD *)(a1 + 16) )
{
v2 = a1 + 33920;
v3 = rwbuff_get_writep(a1 + 33920);
v4 = (unsigned int)rwbuff_get_writen(a1 + 33920);
log_debug("%d space left in remote buffuser.", v4);
if ( (_DWORD)v4 )
{
while ( 1 )
{
v5 = (*(__int64 (__fastcall **)(_QWORD, __int64, _QWORD))(*(_QWORD *)(a1 + 16) + 96LL))(
*(unsigned int *)(a1 + 28),
v3,
(unsigned int)v4);
v6 = v5;
if ( v5 >= 0 )
break;
v7 = *_errno_location();
if ( v7 != 4 )
{
if ( v7 == 11 )
{
LODWORD(v4) = 0;
}
else
{
v9 = strerror(v7);
log_debug("remote read error:%s", v9);
LODWORD(v4) = -2;
}
return (unsigned int)v4;
}
}
if ( v5 )
{
log_debug("%d data are received from remote.", (unsigned int)v5);
*(_DWORD *)(a1 + 67808) = time(0LL);
rwbuff_write(v2, v6);
v10 = rwbuff_get_readp(v2);
v11 = rwbuff_get_readn(v2);
LODWORD(v4) = ((*(int (__fastcall **)(__int64, __int64, _QWORD))(*(_QWORD *)(*(_QWORD *)(a1 + 16) + 16LL) + 40LL))(
a1,
v10,
v11) >> 31) & 0xFFFFFFFD;
}
else
{
*(_DWORD *)(a1 + 67768) = 3;
*(_DWORD *)(a1 + 67808) = time(0LL);
(*(void (__fastcall **)(__int64, _QWORD, _QWORD))(*(_QWORD *)(*(_QWORD *)(a1 + 16) + 16LL) + 40LL))(
a1,
0LL,
0LL);
log_debug("FIN is received from remote.");
LODWORD(v4) = v6;
}
}
}
else
{
log_error("session can not be NULL!");
LODWORD(v4) = -1;
}
return (unsigned int)v4;
}

canonical_decompiled_code:
__int64 __fastcall func6(__int64 a1)
{
__int64 v2; // r14
__int64 v3; // r13
__int64 v4; // r12
int v5; // eax
unsigned int v6; // ebx
int v7; // edi
char *v9; // rax
__int64 v10; // rbx
unsigned int v11; // eax

if ( a1 && *(_QWORD *)(a1 + 16) )
{
v2 = a1 + 33920;
v3 = rwbuff_get_writep(a1 + 33920);
v4 = (unsigned int)rwbuff_get_writen(a1 + 33920);
log_debug("%d space left in remote buffuser.", v4);
if ( (_DWORD)v4 )
{
while ( 1 )
{
v5 = (*(__int64 (__fastcall **)(_QWORD, __int64, _QWORD))(*(_QWORD *)(a1 + 16) + 96LL))(
*(unsigned int *)(a1 + 28),
v3,
(unsigned int)v4);
v6 = v5;
if ( v5 >= 0 )
break;
v7 = *_errno_location();
if ( v7 != 4 )
{
if ( v7 == 11 )
{
LODWORD(v4) = 0;
}
else
{
v9 = strerror(v7);
log_debug("remote read error:%s", v9);
LODWORD(v4) = -2;
}
return (unsigned int)v4;
}
}
if ( v5 )
{
log_debug("%d data are received from remote.", (unsigned int)v5);
*(_DWORD *)(a1 + 67808) = time(0LL);
rwbuff_write(v2, v6);
v10 = rwbuff_get_readp(v2);
v11 = rwbuff_get_readn(v2);
LODWORD(v4) = ((*(int (__fastcall **)(__int64, __int64, _QWORD))(*(_QWORD *)(*(_QWORD *)(a1 + 16) + 16LL) + 40LL))(
a1,
v10,
v11) >> 31) & 0xFFFFFFFD;
}
else
{
*(_DWORD *)(a1 + 67768) = 3;
*(_DWORD *)(a1 + 67808) = time(0LL);
(*(void (__fastcall **)(__int64, _QWORD, _QWORD))(*(_QWORD *)(*(_QWORD *)(a1 + 16) + 16LL) + 40LL))(
a1,
0LL,
0LL);
log_debug("FIN is received from remote.");
LODWORD(v4) = v6;
}
}
}
else
{
log_error("session can not be NULL!");
LODWORD(v4) = -1;
}
return (unsigned int)v4;
}

original_code:
static int session_on_remote_recv(struct fctl_session_t* session){
    if (session == ((void *)0) || session->proxy == ((void *)0)){
        log_error("session can not be NULL!");;
        return -1;
    }
    char * buf = rwbuff_get_writep(&session->remote_buf);
    int space = rwbuff_get_writen(&session->remote_buf);
    log_debug("%d space left in remote buffuser.", space);;
    if ( space == 0) {
        return 0;
    }
    int n;
again:
    n = session->proxy->read(session->remote_fd, buf , space);
    if (n < 0) {
        if ( (*__errno_location ()) == 4) goto again;
        if ( (*__errno_location ()) != 11){
            log_debug("remote read error:%s",strerror((*__errno_location ())));;
            return -2;
        }
        return 0;
    }else if ( n == 0){
        session->remote_status = SESSION_CLOSING;
        session->closing_time = time(0);
        session->proxy->proto->on_remote_rev(session , ((void *)0), 0);
        log_debug("FIN is received from remote.");;
        return 0;
    }
    log_debug("%d data are received from remote.", n);;
    session->closing_time = time(0);
    rwbuff_write(&session->remote_buf , n);
    buf = rwbuff_get_readp(&session->remote_buf);
    space = rwbuff_get_readn(&session->remote_buf);
    int action = session->proxy->proto->on_remote_rev(session , buf, space);
    if (action < 0)
        return -3;
    return 0;
}

canonical_original_code:
static int session_on_remote_recv(struct fctl_session_t *session){
    if (session == ((void *)0) || session->proxy == ((void *)0)){
        log_error("session can not be NULL!");;
        return -1;
    }
    char *buf = rwbuff_get_writep(&session->remote_buf);
    int space = rwbuff_get_writen(&session->remote_buf);
    log_debug("%d space left in remote buffuser.", space);;
    if ( space == 0) {
        return 0;
    }
    int n;
again:
    n = session->proxy->read(session->remote_fd, buf , space);
    if (n < 0) {
        if ( (*__errno_location ()) == 4) goto again;
        if ( (*__errno_location ()) != 11){
            log_debug("remote read error:%s",strerror((*__errno_location ())));;
            return -2;
        }
        return 0;
    }else if ( n == 0){
        session->remote_status = SESSION_CLOSING;
        session->closing_time = time(0);
        session->proxy->proto->on_remote_rev(session , ((void *)0), 0);
        log_debug("FIN is received from remote.");;
        return 0;
    }
    log_debug("%d data are received from remote.", n);;
    session->closing_time = time(0);
    rwbuff_write(&session->remote_buf , n);
    buf = rwbuff_get_readp(&session->remote_buf);
    space = rwbuff_get_readn(&session->remote_buf);
    int action = session->proxy->proto->on_remote_rev(session , buf, space);
    if (action < 0)
        return -3;
    return 0;
}

variable_types: action int


decompiled_code:
__int64 __fastcall session_on_local_recv(__int64 a1)
{
__int64 v2; // r14
__int64 v3; // r13
__int64 v4; // r12
int v5; // eax
unsigned int v6; // ebx
int v7; // edi
char *v9; // rax
__int64 v10; // rbx

if ( a1 && *(_QWORD *)(a1 + 16) )
{
v2 = a1 + 72;
v3 = rwbuff_get_writep(a1 + 72);
v4 = (unsigned int)rwbuff_get_writen(a1 + 72);
log_debug("%d space left in local buffer.", v4);
if ( (_DWORD)v4 )
{
while ( 1 )
{
v5 = (*(__int64 (__fastcall **)(_QWORD, __int64, _QWORD))(*(_QWORD *)(a1 + 16) + 96LL))(
*(unsigned int *)(a1 + 24),
v3,
(unsigned int)v4);
v6 = v5;
if ( v5 >= 0 )
break;
v7 = *_errno_location();
if ( v7 != 4 )
{
if ( v7 == 11 )
{
LODWORD(v4) = 0;
}
else
{
v9 = strerror(v7);
log_debug("read error:%s", v9);
LODWORD(v4) = -2;
}
return (unsigned int)v4;
}
}
if ( v5 )
{
log_debug("%d data are received from local.", (unsigned int)v5);
*(_DWORD *)(a1 + 67808) = time(0LL);
rwbuff_write(v2, v6);
v4 = rwbuff_get_readp(v2);
v10 = (unsigned int)rwbuff_get_readn(v2);
log_debug("there are %d data to be handled by protocal handler.", v10);
*(_BYTE *)(v4 + (int)v10) = 0;
LODWORD(v4) = (*(int (__fastcall **)(__int64, __int64, _QWORD))(*(_QWORD *)(*(_QWORD *)(a1 + 16) + 16LL) + 32LL))(
a1,
v4,
(unsigned int)v10) >> 31;
}
else
{
*(_DWORD *)(a1 + 67772) = 3;
*(_DWORD *)(a1 + 67808) = time(0LL);
log_debug("FIN is received from local.");
LODWORD(v4) = v6;
}
}
}
else
{
log_error("session can not be NULL!");
LODWORD(v4) = -1;
}
return (unsigned int)v4;
}

canonical_decompiled_code:
__int64 __fastcall func7(__int64 a1)
{
__int64 v2; // r14
__int64 v3; // r13
__int64 v4; // r12
int v5; // eax
unsigned int v6; // ebx
int v7; // edi
char *v9; // rax
__int64 v10; // rbx

if ( a1 && *(_QWORD *)(a1 + 16) )
{
v2 = a1 + 72;
v3 = rwbuff_get_writep(a1 + 72);
v4 = (unsigned int)rwbuff_get_writen(a1 + 72);
log_debug("%d space left in local buffer.", v4);
if ( (_DWORD)v4 )
{
while ( 1 )
{
v5 = (*(__int64 (__fastcall **)(_QWORD, __int64, _QWORD))(*(_QWORD *)(a1 + 16) + 96LL))(
*(unsigned int *)(a1 + 24),
v3,
(unsigned int)v4);
v6 = v5;
if ( v5 >= 0 )
break;
v7 = *_errno_location();
if ( v7 != 4 )
{
if ( v7 == 11 )
{
LODWORD(v4) = 0;
}
else
{
v9 = strerror(v7);
log_debug("read error:%s", v9);
LODWORD(v4) = -2;
}
return (unsigned int)v4;
}
}
if ( v5 )
{
log_debug("%d data are received from local.", (unsigned int)v5);
*(_DWORD *)(a1 + 67808) = time(0LL);
rwbuff_write(v2, v6);
v4 = rwbuff_get_readp(v2);
v10 = (unsigned int)rwbuff_get_readn(v2);
log_debug("there are %d data to be handled by protocal handler.", v10);
*(_BYTE *)(v4 + (int)v10) = 0;
LODWORD(v4) = (*(int (__fastcall **)(__int64, __int64, _QWORD))(*(_QWORD *)(*(_QWORD *)(a1 + 16) + 16LL) + 32LL))(
a1,
v4,
(unsigned int)v10) >> 31;
}
else
{
*(_DWORD *)(a1 + 67772) = 3;
*(_DWORD *)(a1 + 67808) = time(0LL);
log_debug("FIN is received from local.");
LODWORD(v4) = v6;
}
}
}
else
{
log_error("session can not be NULL!");
LODWORD(v4) = -1;
}
return (unsigned int)v4;
}

original_code:
static int session_on_local_recv(struct fctl_session_t* session){
    if (session == ((void *)0) || session->proxy == ((void *)0)){
        log_error("session can not be NULL!");;
        return -1;
    }
    char * local_buf = rwbuff_get_writep(&session->local_buf);
    int space = rwbuff_get_writen(&session->local_buf);
    log_debug("%d space left in local buffer.", space);;
    if ( space == 0) {
        return 0;
    }
    int n;
 again:
    n = session->proxy->read(session->local_fd, local_buf , space);
    if (n < 0) {
        if ( (*__errno_location ()) == 4) goto again;
        if ( (*__errno_location ()) != 11) {
            log_debug("read error:%s",strerror((*__errno_location ())));;
            return -2;
        }else
            return 0;
    }else if ( n == 0){
        session->local_status = SESSION_CLOSING;
        session->closing_time = time(0);
        log_debug("FIN is received from local.");;
        return 0;
    }
    log_debug("%d data are received from local.", n);;
     session->closing_time = time(0);
    rwbuff_write(&session->local_buf , n);
    local_buf = rwbuff_get_readp(&session->local_buf);
    space = rwbuff_get_readn(&session->local_buf);
    log_debug("there are %d data to be handled by protocal handler.", space);;
    local_buf[space] = '\0';
    int action = session->proxy->proto->on_local_rev(session , local_buf, space);
    if ( action < 0 )
        return -1;
    return 0;
}

canonical_original_code:
static int session_on_local_recv(struct fctl_session_t *session){
    if (session == ((void *)0) || session->proxy == ((void *)0)){
        log_error("session can not be NULL!");;
        return -1;
    }
    char *local_buf = rwbuff_get_writep(&session->local_buf);
    int space = rwbuff_get_writen(&session->local_buf);
    log_debug("%d space left in local buffer.", space);;
    if ( space == 0) {
        return 0;
    }
    int n;
 again:
    n = session->proxy->read(session->local_fd, local_buf , space);
    if (n < 0) {
        if ( (*__errno_location ()) == 4) goto again;
        if ( (*__errno_location ()) != 11) {
            log_debug("read error:%s",strerror((*__errno_location ())));;
            return -2;
        }else
            return 0;
    }else if ( n == 0){
        session->local_status = SESSION_CLOSING;
        session->closing_time = time(0);
        log_debug("FIN is received from local.");;
        return 0;
    }
    log_debug("%d data are received from local.", n);;
     session->closing_time = time(0);
    rwbuff_write(&session->local_buf , n);
    local_buf = rwbuff_get_readp(&session->local_buf);
    space = rwbuff_get_readn(&session->local_buf);
    log_debug("there are %d data to be handled by protocal handler.", space);;
    local_buf[space] = '\0';
    int action = session->proxy->proto->on_local_rev(session , local_buf, space);
    if ( action < 0 )
        return -1;
    return 0;
}


decompiled_code:
void __fastcall session_free(void *a1)
{
if ( a1 )
free(a1);
else
log_error("session can not be NULL!");
}

canonical_decompiled_code:
void __fastcall func8(void *a1)
{
if ( a1 )
free(a1);
else
log_error("session can not be NULL!");
}

original_code:
static int session_free(struct fctl_session_t* session){
     if (session == ((void *)0)){
        log_error("session can not be NULL!");;
        return -1;
    }
    free(session);
}

canonical_original_code:
static int session_free(struct fctl_session_t *session){
     if (session == ((void *)0)){
        log_error("session can not be NULL!");;
        return -1;
    }
    free(session);
}


decompiled_code:
__int64 __fastcall pc_add_proxy(int *a1, __int64 a2)
{
int v2; // eax

v2 = *a1;
if ( *a1 > 8 )
return 0xFFFFFFFFLL;
*a1 = v2 + 1;
*(_QWORD *)&a1[2 * v2 + 2] = a2;
return 0LL;
}

canonical_decompiled_code:
__int64 __fastcall func0(int *a1, __int64 a2)
{
int v2; // eax

v2 = *a1;
if ( *a1 > 8 )
return 0xFFFFFFFFLL;
*a1 = v2 + 1;
*(_QWORD *)&a1[2 * v2 + 2] = a2;
return 0LL;
}

original_code:
int pc_add_proxy(struct proxy_container_t* pc, struct fctl_proxy_t* proxy){
    if (pc->index >= (10 -1))
        return -1;
    pc->proxies[pc->index++] = proxy;
    return 0;
}

canonical_original_code:
int pc_add_proxy(struct proxy_container_t *pc, struct fctl_proxy_t *proxy){
    if (pc->index >= (10 -1))
        return -1;
    pc->proxies[pc->index++] = proxy;
    return 0;
}

variable_types: struct proxy_container_t { int index; struct fctl_proxy_t { int daemon; int port; int pid; struct fctl_proto_t { char proto_name[20]; int port; enum PROXY_TYPE { PROXY_SYN=0, PROXY_ASY=1 } proxy_type; int (*on_local_rev)(struct fctl_session_t { struct list_head { struct list_head *next; } list; struct fctl_proxy_t *proxy; int local_fd; int remote_fd; struct sockaddr_in { unsigned short sin_family; unsigned short sin_port; struct in_addr { unsigned int s_addr; } sin_addr; unsigned char sin_zero[-1]; } local_addr; int remote_src_port; int remote_dst_port; struct sockaddr_in remote_addr; struct rwbuff_t { char buf[-1]; char *readp; char *writep; char *sendp; int buf_len; int buf_default_len; struct cache_pool_t { int cache_count; struct list_head cache_head; } cache_pool; } local_buf; struct rwbuff_t remote_buf; int remote_status; int local_status; int proto_status; int local_retry_times; int remote_retry_times; void *private_data; long create_time; int closing_time; struct fctl_spool_t { int fd; char name[512]; int size; int exists; } spool; int session_id; int (*on_local_recv)(struct fctl_session_t *); int (*on_remote_recv)(struct fctl_session_t *); int (*on_local_send)(struct fctl_session_t *); int (*on_remote_send)(struct fctl_session_t *); int (*on_local_close)(struct fctl_session_t *); int (*on_local_connect)(struct fctl_session_t *); int (*on_remote_close)(struct fctl_session_t *); int (*on_remote_connect)(struct fctl_session_t *); int (*is_closed)(struct fctl_session_t *); int (*close)(struct fctl_session_t *); int (*free)(struct fctl_session_t *); } *, char *, int); int (*on_remote_rev)(struct fctl_session_t *, char *, int); int (*on_connect)(struct fctl_session_t *); int (*on_disconnect)(struct fctl_session_t *); int (*on_notification)(struct fctl_session_t *, struct event_header_t { int session_id; int event_type; int event_len; } *); } *proto; int valid_port; int max_bind_port; int min_bind_port; char proto_name[20]; unsigned int cur_session_id; struct list_head session_head; int (*run)(struct fctl_proxy_t *); int (*get_port)(struct fctl_proxy_t *); int (*read)(int, char *, int); int (*write)(int, char *, int); int (*listen)(struct fctl_proxy_t *); int (*local_send)(struct fctl_proxy_t *, struct fctl_session_t *); int (*remote_send)(struct fctl_proxy_t *, struct fctl_session_t *); int (*local_close)(struct fctl_proxy_t *, struct fctl_session_t *); int (*remote_close)(struct fctl_proxy_t *, struct fctl_session_t *); int (*remote_connect)(struct fctl_proxy_t *, struct fctl_session_t *, char *, int); } *proxies[10]; int others_count; struct other_process_t { int pid; int daemon; char filename[512]; char arg1[1024]; } others[64]; } *

variable_types:
proxy
struct fctl_proxy_t *

user_defined_types: struct proxy_container_t { int index; struct fctl_proxy_t *proxies[10]; int others_count; struct other_process_t others[64]; }


original_code:
int pc_run_all(struct proxy_container_t* pc){
    int i =0;
    for(i = 0 ; i < pc->others_count; i++ ){
       pid_t pid;
       if ((pid = fork()) < 0) {
           pid = 0;
       } else if (pid == 0) {
           int ret = 0;
           if (pc->others[i].arg1[0] == 0)
               ret = execl(pc->others[i].filename ,pc->others[i].filename, (char*)0);
           else
               ret = execl(pc->others[i].filename ,pc->others[i].filename, pc->others[i].arg1, (char*)0);
           log_error("execute %s error: %s\n", pc->others[i].filename, strerror((*__errno_location ())));;
           exit(0);
       }
       printf("%s started\n",pc->others[i].filename);
       sleep(1);
       pc->others[i].pid = pid;
    }
    for(i = 0 ; i < pc->index; i++ ){
        pc->proxies[i]->run( pc->proxies[i]);
    }
    return 0 ;
}

canonical_original_code:
int pc_run_all(struct proxy_container_t *pc){
    int i = 0;
    for(i = 0 ; i < pc->others_count; i++ ){
       int pid;
       if ((pid = fork()) < 0) {
           pid = 0;
       } else if (pid == 0) {
           int ret = 0;
           if (pc->others[i].arg1[0] == 0)
               ret = execl(pc->others[i].filename ,pc->others[i].filename, (char *)0);
           else
               ret = execl(pc->others[i].filename ,pc->others[i].filename, pc->others[i].arg1, (char *)0);
           log_error("execute %s error: %s\n", pc->others[i].filename, strerror((*__errno_location ())));;
           exit(0);
       }
       printf("%s started\n",pc->others[i].filename);
       sleep(1);
       pc->others[i].pid = pid;
    }
    for(i = 0 ; i < pc->index; i++ ){
        pc->proxies[i]->run( pc->proxies[i]);
    }
    return 0 ;
}

variable_types: i int

variable_types: pid int

variable_types: ret int

user_defined_types: struct other_process_t { int pid; int daemon; char filename[512]; char arg1[1024]; }


original_code:
int pc_kill_all(struct proxy_container_t* pc, int signo){
    int i =0;
    for(i = 0 ; i < pc->index; i++ ){
        if (pc->proxies[i]->pid >0)
        kill(pc->proxies[i]->pid , signo);
    }
    for(i = 0 ; i < pc->others_count; i++ ){
        if (pc->others[i].pid >0)
            kill(pc->others[i].pid , signo);
    }
    return 0 ;
}

canonical_original_code:
int pc_kill_all(struct proxy_container_t *pc, int signo){
    int i = 0;
    for(i = 0 ; i < pc->index; i++ ){
        if (pc->proxies[i]->pid >0)
        kill(pc->proxies[i]->pid , signo);
    }
    for(i = 0 ; i < pc->others_count; i++ ){
        if (pc->others[i].pid >0)
            kill(pc->others[i].pid , signo);
    }
    return 0 ;
}

variable_types: signo int

user_defined_types: struct fctl_proto_t { char proto_name[20]; int port; enum PROXY_TYPE proxy_type; int (*on_local_rev)(struct fctl_session_t *, char *, int); int (*on_remote_rev)(struct fctl_session_t *, char *, int); int (*on_connect)(struct fctl_session_t *); int (*on_disconnect)(struct fctl_session_t *); int (*on_notification)(struct fctl_session_t *, struct event_header_t *); }


original_code:
int pc_restart_proxy(struct proxy_container_t* pc, pid_t proxy_pid){
   int i =0;
    for(i = 0 ; i < pc->index; i++ ){
        if (pc->proxies[i]->pid == proxy_pid){
            pc->proxies[i]->run( pc->proxies[i]);
            break;
        }
    }
    return 0 ;
}

canonical_original_code:
int pc_restart_proxy(struct proxy_container_t *pc, int proxy_pid){
   int i = 0;
    for(i = 0 ; i < pc->index; i++ ){
        if (pc->proxies[i]->pid == proxy_pid){
            pc->proxies[i]->run( pc->proxies[i]);
            break;
        }
    }
    return 0 ;
}

user_defined_types: struct fctl_session_t { struct list_head list; struct fctl_proxy_t *proxy; int local_fd; int remote_fd; struct sockaddr_in local_addr; int remote_src_port; int remote_dst_port; struct sockaddr_in remote_addr; struct rwbuff_t local_buf; struct rwbuff_t remote_buf; int remote_status; int local_status; int proto_status; int local_retry_times; int remote_retry_times; void *private_data; long create_time; int closing_time; struct fctl_spool_t spool; int session_id; int (*on_local_recv)(struct fctl_session_t *); int (*on_remote_recv)(struct fctl_session_t *); int (*on_local_send)(struct fctl_session_t *); int (*on_remote_send)(struct fctl_session_t *); int (*on_local_close)(struct fctl_session_t *); int (*on_local_connect)(struct fctl_session_t *); int (*on_remote_close)(struct fctl_session_t *); int (*on_remote_connect)(struct fctl_session_t *); int (*is_closed)(struct fctl_session_t *); int (*close)(struct fctl_session_t *); int (*free)(struct fctl_session_t *); }


original_code:
int pc_remove_pid(struct proxy_container_t* pc, pid_t proxy_pid){
   int i =0;
    for(i = 0 ; i < pc->index; i++ ){
        if (pc->proxies[i]->pid == proxy_pid){
            pc->proxies[i]->pid = 0;
            break;
        }
    }
    for(i = 0 ; i < pc->others_count; i++ ){
        if (pc->others[i].pid == proxy_pid ){
                pc->others[i].pid = 0;
            break;
        }
    }
    return 0 ;
}

canonical_original_code:
int pc_remove_pid(struct proxy_container_t *pc, int proxy_pid){
   int i = 0;
    for(i = 0 ; i < pc->index; i++ ){
        if (pc->proxies[i]->pid == proxy_pid){
            pc->proxies[i]->pid = 0;
            break;
        }
    }
    for(i = 0 ; i < pc->others_count; i++ ){
        if (pc->others[i].pid == proxy_pid ){
                pc->others[i].pid = 0;
            break;
        }
    }
    return 0 ;
}

user_defined_types: struct sockaddr_in { unsigned short sin_family; unsigned short sin_port; struct in_addr sin_addr; unsigned char sin_zero[-1]; }


original_code:
int pc_add_others(struct proxy_container_t* pc, int daemon, char* filename, char* arg1){
    strncpy(pc->others[pc->others_count].filename, filename , 512 -1);
    pc->others[pc->others_count].daemon = daemon;
    if (arg1 != ((void *)0))
        strncpy(pc->others[pc->others_count].arg1, arg1 , sizeof(pc->others[pc->others_count].arg1)-1);
    pc->others_count++;
    return 0;
}

canonical_original_code:
int pc_add_others(struct proxy_container_t *pc, int daemon, char *filename, char *arg1){
    strncpy(pc->others[pc->others_count].filename, filename , 512 -1);
    pc->others[pc->others_count].daemon = daemon;
    if (arg1 != ((void *)0))
        strncpy(pc->others[pc->others_count].arg1, arg1 , sizeof(pc->others[pc->others_count].arg1)-1);
    pc->others_count++;
    return 0;
}

variable_types: daemon int

variable_types:
filename
char *

user_defined_types: struct rwbuff_t { char buf[-1]; char *readp; char *writep; char *sendp; int buf_len; int buf_default_len; struct cache_pool_t cache_pool; }


original_code:
int pc_stop_others(struct proxy_container_t* pc, char* filename ){
    int i = 0;
     for(i = 0 ; i < pc->others_count; i++ ){
        if ( strcmp(pc->others[i].filename , filename) == 0 ){
            if ( pc->others[i].pid > 0){
                kill(pc->others[i].pid , 2);
                pc->others[i].pid = 0;
            }
            break;
        }
    }
    return 0;
}

canonical_original_code:
int pc_stop_others(struct proxy_container_t *pc, char *filename){
    int i = 0;
     for(i = 0 ; i < pc->others_count; i++ ){
        if ( strcmp(pc->others[i].filename , filename) == 0 ){
            if ( pc->others[i].pid > 0){
                kill(pc->others[i].pid , 2);
                pc->others[i].pid = 0;
            }
            break;
        }
    }
    return 0;
}

user_defined_types: struct fctl_proxy_t { int daemon; int port; int pid; struct fctl_proto_t *proto; int valid_port; int max_bind_port; int min_bind_port; char proto_name[20]; unsigned int cur_session_id; struct list_head session_head; int (*run)(struct fctl_proxy_t *); int (*get_port)(struct fctl_proxy_t *); int (*read)(int, char *, int); int (*write)(int, char *, int); int (*listen)(struct fctl_proxy_t *); int (*local_send)(struct fctl_proxy_t *, struct fctl_session_t *); int (*remote_send)(struct fctl_proxy_t *, struct fctl_session_t *); int (*local_close)(struct fctl_proxy_t *, struct fctl_session_t *); int (*remote_close)(struct fctl_proxy_t *, struct fctl_session_t *); int (*remote_connect)(struct fctl_proxy_t *, struct fctl_session_t *, char *, int); }


original_code:
int pc_restart_others(struct proxy_container_t* pc, pid_t pid ){
    int i = 0;
    for(i = 0 ; i < pc->others_count; i++ ){
        if ( pc->others[i].pid == pid ){
            pid_t pid;
            if ((pid = fork()) < 0) {
                pid = 0;
            } else if (pid == 0) {
                int ret = 0;
                if (pc->others[i].arg1[0] == 0)
                    ret = execl(pc->others[i].filename ,pc->others[i].filename, (char*)0);
                else
                    ret = execl(pc->others[i].filename ,pc->others[i].filename, pc->others[i].arg1, (char*)0);
                log_error("execute %s error: %s\n", pc->others[i].filename, strerror((*__errno_location ())));;
                exit(0);
            }
            pc->others[i].pid = pid;
            break;
        }
    }
    return 0;
}

canonical_original_code:
int pc_restart_others(struct proxy_container_t *pc, int pid){
    int i = 0;
    for(i = 0 ; i < pc->others_count; i++ ){
        if ( pc->others[i].pid == pid ){
            int pid;
            if ((pid = fork()) < 0) {
                pid = 0;
            } else if (pid == 0) {
                int ret = 0;
                if (pc->others[i].arg1[0] == 0)
                    ret = execl(pc->others[i].filename ,pc->others[i].filename, (char *)0);
                else
                    ret = execl(pc->others[i].filename ,pc->others[i].filename, pc->others[i].arg1, (char *)0);
                log_error("execute %s error: %s\n", pc->others[i].filename, strerror((*__errno_location ())));;
                exit(0);
            }
            pc->others[i].pid = pid;
            break;
        }
    }
    return 0;
}


decompiled_code:
__int64 nat_disable_port()
{
return 0LL;
}

canonical_decompiled_code:
__int64 func0()
{
return 0LL;
}

original_code:
int nat_disable_port(int src_port , int dst_port ){
    return (0);
}

canonical_original_code:
int nat_disable_port(int src_port, int dst_port){
    return (0);
}


decompiled_code:
__int64 nat_enable_port()
{
return 0LL;
}

canonical_decompiled_code:
__int64 func1()
{
return 0LL;
}

original_code:
int nat_enable_port(int src_port , int dst_port ){
    return (0);
}

canonical_original_code:
int nat_enable_port(int src_port, int dst_port){
    return (0);
}


decompiled_code:
int init_iptables_nat_rules()
{
char v1[136]; // [rsp+0h] [rbp-88h] BYREF

snprintf(v1, 0x80uLL, "%s -t nat -F", (const char *)(unsigned int)((_DWORD)&g_conf + 1536));
system(v1);
snprintf(
v1,
0x80uLL,
"%s -t nat -A OUTPUT -m owner --uid-owner 0 -j ACCEPT",
(const char *)(unsigned int)((_DWORD)&g_conf + 1536));
return system(v1);
}

canonical_decompiled_code:
int func2()
{
char v1[136]; // [rsp+0h] [rbp-88h] BYREF

snprintf(v1, 0x80uLL, "%s -t nat -F", (const char *)(unsigned int)((_DWORD)&g_conf + 1536));
system(v1);
snprintf(
v1,
0x80uLL,
"%s -t nat -A OUTPUT -m owner --uid-owner 0 -j ACCEPT",
(const char *)(unsigned int)((_DWORD)&g_conf + 1536));
return system(v1);
}

original_code:
void init_iptables_nat_rules(){
    char cmd[128];
    snprintf(cmd , sizeof(cmd), "%s -t nat -F", g_conf.iptables);
 system(cmd);
 snprintf(cmd , sizeof(cmd), "%s -t nat -A OUTPUT -m owner --uid-owner 0 -j ACCEPT", g_conf.iptables);
 system(cmd);
}

variable_types:
cmd
char [128]


decompiled_code:
int __fastcall create_iptables_nat_rule(unsigned int a1, unsigned int a2)
{
char v3[136]; // [rsp+0h] [rbp-88h] BYREF

snprintf(
v3,
0x80uLL,
"%s -t nat -A OUTPUT -p tcp --dport %d -j REDIRECT --to-ports %d",
(const char *)(unsigned int)((_DWORD)&g_conf + 1536),
a1,
a2);
puts(v3);
return system(v3);
}

canonical_decompiled_code:
int __fastcall func3(unsigned int a1, unsigned int a2)
{
char v3[136]; // [rsp+0h] [rbp-88h] BYREF

snprintf(
v3,
0x80uLL,
"%s -t nat -A OUTPUT -p tcp --dport %d -j REDIRECT --to-ports %d",
(const char *)(unsigned int)((_DWORD)&g_conf + 1536),
a1,
a2);
puts(v3);
return system(v3);
}

original_code:
void create_iptables_nat_rule(int dest_port , int redirect_port){
    char cmd[128];
    snprintf(cmd , sizeof(cmd), "%s -t nat -A OUTPUT -p tcp --dport %d -j REDIRECT --to-ports %d" ,
         g_conf.iptables, dest_port, redirect_port);
    printf("%s\n", cmd);
    system(cmd);
}

canonical_original_code:
void create_iptables_nat_rule(int dest_port, int redirect_port){
    char cmd[128];
    snprintf(cmd , sizeof(cmd), "%s -t nat -A OUTPUT -p tcp --dport %d -j REDIRECT --to-ports %d" ,
         g_conf.iptables, dest_port, redirect_port);
    printf("%s\n", cmd);
    system(cmd);
}


decompiled_code:
int destroy_iptables_nat_rules()
{
char v1[136]; // [rsp+0h] [rbp-88h] BYREF

snprintf(v1, 0x80uLL, "%s -t nat -F", (const char *)(unsigned int)((_DWORD)&g_conf + 1536));
return system(v1);
}

canonical_decompiled_code:
int func4()
{
char v1[136]; // [rsp+0h] [rbp-88h] BYREF

snprintf(v1, 0x80uLL, "%s -t nat -F", (const char *)(unsigned int)((_DWORD)&g_conf + 1536));
return system(v1);
}

original_code:
void destroy_iptables_nat_rules(){
    char cmd[128];
    snprintf(cmd , sizeof(cmd), "%s -t nat -F", g_conf.iptables);
 system(cmd);
}