// File: /workspace/github_c_makefile_star2_O2/niuyuling[P]CProxy/main.c
// Function: main
void _main(int argc, char *argv[])
{
    char *p = NULL;
    int longindex = 0;
    int opt;
    char path[CACHE_SIZE] = { 0 };
    char executable_filename[CACHE_SIZE] = { 0 };
    (void)get_executable_path(path, executable_filename, sizeof(path));
    char *inifile = "/CProxy.conf";
    struct rlimit rt;
    inifile = strcat(path, inifile);
    conf *configure = (struct CONF *)malloc(sizeof(struct CONF));
    memset(configure, 0, sizeof(struct CONF));
    read_conf(inifile, configure);

    sslEncodeCode = 0;          // 默认SSL不转码

    char optstring[] = ":l:f:t:p:c:e:s:h?";
    static struct option longopts[] = {
        { "local_address", required_argument, 0, 'l' },
        { "remote_address", required_argument, 0, 'f' },
        { "timeout", required_argument, 0, 't' },
        { "process", required_argument, 0, 'p' },
        { "config", required_argument, 0, 'c' },
        { "coding", required_argument, 0, 'e' },
        { "signal", required_argument, 0, 's' },
        { "help", no_argument, 0, 'h' },
        { "?", no_argument, 0, '?' },
        { 0, 0, 0, 0 }
    };
    while (-1 != (opt = getopt_long(argc, argv, optstring, longopts, &longindex))) {
        switch (opt) {
        case 'l':
            p = strchr(optarg, ':');
            if (p) {
                strncpy(local_host, optarg, p - optarg);
                local_port = atoi(p + 1);
            } else {
                strncpy(local_host, optarg, strlen(local_host));
            }
            break;
        case 'f':
            p = strchr(optarg, ':');
            if (p) {
                strncpy(remote_host, optarg, p - optarg);
                remote_port = atoi(p + 1);
            } else {
                strncpy(remote_host, optarg, strlen(remote_host));
            }
            break;
        case 't':
            timeout_minute = (time_t) atoi(optarg); // 如果指定-t,优先使用参数提供的值(输入值 > 配置文件读取的值)
            break;
        case 'p':
            process = atoi(optarg);
            break;
        case 'c':
            free_tcp(&http_head_strrep);
            free_tcp(&http_head_regrep);
            free_tcp(&https_head_strrep);
            free_tcp(&https_head_regrep);
            free_conf(configure);
            memset(configure, 0, sizeof(struct CONF));
            read_conf(optarg, configure);
            break;
        case 'e':
            sslEncodeCode = atoi(optarg);
            break;
        case 's':
            if (strcasecmp(optarg, "stop") == 0 || strcasecmp(optarg, "quit") == 0) {
                free_conf(configure);
                exit(process_signal(SERVER_TYPE_STOP, executable_filename));
            }
            if (strcasecmp(optarg, "restart") == 0 || strcasecmp(optarg, "reload") == 0) {
                process_signal(SERVER_TYPE_STOP, executable_filename);
                while (process_signal(SERVICE_TYPE_STATUS_NOT_PRINT, executable_filename) == 0) ;
            }
            if (strcasecmp(optarg, "status") == 0)
                exit(process_signal(SERVER_TYPE_STATUS, executable_filename));
            break;
        case 'h':
        case '?':
            help_information();
            exit(0);
            break;
        default:
            ;
        }
    }
    
    
    signal(SIGPIPE, SIG_IGN);
#if DAEMON
    // 守护进程
    int nochdir = 1;
    int noclose = 1;
    int pid;
    if ((pid = fork()) < 0) {
        return;
    } else if (0 != pid) {
        free_tcp(&http_head_strrep);
        free_tcp(&http_head_regrep);
        free_tcp(&https_head_strrep);
        free_tcp(&https_head_regrep);
        free_conf(configure);
        free(configure);
        exit(0);
    }

    if (setsid() < 0) {
        return;
    }

    signal(SIGHUP, SIG_IGN);
    if ((pid = fork()) < 0) {
        return;
    } else if (0 != pid) {
        free_tcp(&http_head_strrep);
        free_tcp(&http_head_regrep);
        free_tcp(&https_head_strrep);
        free_tcp(&https_head_regrep);
        free_conf(configure);
        free(configure);
        exit(0);
    }

    if (0 == nochdir) {
        chdir("/");
    }

    if (0 == noclose) {
        freopen("/dev/null", "r", stdin);
        freopen("/dev/null", "w", stdout);
        freopen("/dev/null", "w", stderr);
    }
#endif



    // 反转链表，使读取的配置正序
    http_head_strrep = local_reverse(http_head_strrep);
    http_head_regrep = local_reverse(http_head_regrep);

    https_head_strrep = local_reverse(https_head_strrep);
    https_head_regrep = local_reverse(https_head_regrep);

/*
    print_tcp(https_head_strrep);
    print_tcp(https_head_regrep);
    free_tcp(&https_head_strrep);
    free_tcp(&https_head_regrep);
    
    print_tcp(http_head_strrep);
    print_tcp(http_head_regrep);
    free_tcp(&http_head_strrep);
    free_tcp(&http_head_regrep);
    
    free_conf(configure);
    free(configure);
    exit(0);
*/

    
    rt.rlim_max = rt.rlim_cur = MAX_CONNECTION * 2; // 设置每个进程允许打开的最大文件数
    if (setrlimit(RLIMIT_NOFILE, &rt) == -1)
        perror("setrlimit");
    initialize(configure);
    
    
    if (setegid(configure->uid) == -1 || seteuid(configure->uid) == -1) // 设置uid
        exit(1);
        
    while (configure->process-- > 1 && (child_pid = fork()) == 0);
    
    epollfd = epoll_create(MAX_CONNECTION);
    if (epollfd == -1) {
        perror("epoll_create");
        exit(1);
    }

    thread_loop(configure);

    return;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x278, %rsp            # imm = 0x278
movq %rsi, %r13
movl %edi, %ebp
leaq 0xc(%rsp), %r14
andl $0x0, (%r14)
leaq 0x160(%rsp), %rbx
movl $0x10e, %edx            # imm = 0x10E
movq %rbx, %rdi
xorl %esi, %esi
callq 0x21b0
leaq 0x50(%rsp), %r12
movl $0x10e, %edx            # imm = 0x10E
movq %r12, %rdi
xorl %esi, %esi
callq 0x21b0
movq %rbx, %rdi
movq %r12, %rsi
movl $0x10e, %edx            # imm = 0x10E
callq 0x2bb1
movq %rbx, %rdi
callq 0x2140
movabsq $0x2e79786f7250432f, %rcx # imm = 0x2E79786F7250432F
movq %rcx, 0x160(%rsp,%rax)
movabsq $0x666e6f632e7978, %rcx # imm = 0x666E6F632E7978
movq %rcx, 0x165(%rsp,%rax)
pushq $0x1
popq %rdi
movl $0xc0, %esi
callq 0x2270
movq %rbx, %rdi
movq %r14, %rbx
movq %rax, 0x18(%rsp)
movq %rax, %rsi
callq 0x7538
leaq 0x1653d(%rip), %rax     # 0x19664
andl $0x0, (%rax)
movaps 0x61af(%rip), %xmm0     # 0x92e0
leaq 0x20(%rsp), %rax
movaps %xmm0, (%rax)
movw $0x3f, 0x10(%rax)
leaq 0x5eca(%rip), %r14      # 0x9010
pushq $0x4
popq %r15
movq %r13, 0x10(%rsp)
movl %ebp, %edi
movq %r13, %rsi
leaq 0x20(%rsp), %rdx
leaq 0x9170(%rip), %rcx      # 0xc2d0
movq %rbx, %r8
callq 0x2150
leal -0x63(%rax), %ecx
cmpl $0x11, %ecx
ja 0x3377
movslq (%r14,%rcx,4), %rax
addq %r14, %rax
jmpq *%rax
leaq 0x16364(%rip), %rdi     # 0x194e8
callq 0x7470
leaq 0x16360(%rip), %rdi     # 0x194f0
callq 0x7470
leaq 0x1635c(%rip), %rdi     # 0x194f8
callq 0x7470
leaq 0x16358(%rip), %rdi     # 0x19500
callq 0x7470
movq 0x18(%rsp), %rbx
movq %rbx, %rdi
callq 0x74cd
movl $0xc0, %edx
movq %rbx, %rdi
xorl %esi, %esi
callq 0x21b0
movq 0x8e00(%rip), %rax      # 0xbfd0
movq (%rax), %rdi
movq %rbx, %rsi
leaq 0xc(%rsp), %rbx
callq 0x7538
jmp 0x314f
movq 0x8de4(%rip), %rax      # 0xbfd0
movq (%rax), %rdi
callq 0x2480
leaq 0x16345(%rip), %rcx     # 0x19540
movl %eax, (%rcx)
jmp 0x314f
movq 0x8dc7(%rip), %rax      # 0xbfd0
movq (%rax), %rdi
callq 0x2480
movl %eax, 0x16165(%rip)     # 0x1937c
jmp 0x314f
movq 0x8dad(%rip), %rax      # 0xbfd0
movq (%rax), %rdi
callq 0x2480
leaq 0x16432(%rip), %rcx     # 0x19664
movl %eax, (%rcx)
jmp 0x314f
movq 0x8d90(%rip), %rax      # 0xbfd0
movq (%rax), %r13
movq %r13, %rdi
pushq $0x3a
popq %rsi
callq 0x2160
testq %rax, %rax
je 0x338a
movq %rax, %rbx
movq %rax, %rdx
subq %r13, %rdx
leaq 0x16169(%rip), %rdi     # 0x193d0
movq %r13, %rsi
callq 0x2060
incq %rbx
movq %rbx, %rdi
callq 0x2480
movl %eax, 0x16260(%rip)     # 0x194e0
jmp 0x33b0
movq 0x8d44(%rip), %rax      # 0xbfd0
movq (%rax), %r13
movq %r13, %rdi
pushq $0x3a
popq %rsi
callq 0x2160
testq %rax, %rax
je 0x3393
movq %rax, %rbx
movq %rax, %rdx
subq %r13, %rdx
leaq 0x1629d(%rip), %rdi     # 0x19550
movq %r13, %rsi
callq 0x2060
incq %rbx
movq %rbx, %rdi
callq 0x2480
leaq 0x16393(%rip), %rcx     # 0x19660
movl %eax, (%rcx)
jmp 0x33b0
movq 0x8cf5(%rip), %rax      # 0xbfd0
movq (%rax), %r13
movq %r13, %rdi
leaq 0x5e86(%rip), %rsi      # 0x916e
callq 0x2040
testl %eax, %eax
je 0x3507
movq %r13, %rdi
leaq 0x5e74(%rip), %rsi      # 0x9173
callq 0x2040
testl %eax, %eax
je 0x3507
movq %r13, %rdi
leaq 0x5e62(%rip), %rsi      # 0x9178
callq 0x2040
testl %eax, %eax
je 0x3332
movq %r13, %rdi
leaq 0x5e57(%rip), %rsi      # 0x9180
callq 0x2040
testl %eax, %eax
jne 0x3356
pushq $0x1
popq %rdi
movq %r12, %rsi
callq 0x2a2d
movl %r15d, %edi
movq %r12, %rsi
callq 0x2a2d
testl %eax, %eax
je 0x333d
movq 0x8c7d(%rip), %rax      # 0xbfd0
movq (%rax), %r13
movq %r13, %rdi
leaq 0x5eb3(%rip), %rsi      # 0x9213
callq 0x2040
testl %eax, %eax
movq 0x10(%rsp), %r13
jne 0x314f
jmp 0x3521
cmpl $-0x1, %eax
je 0x33bf
cmpl $0x3f, %eax
jne 0x314f
jmp 0x3515
leaq 0x1603f(%rip), %rbx     # 0x193d0
jmp 0x339a
leaq 0x161b6(%rip), %rbx     # 0x19550
movq %rbx, %rdi
callq 0x2140
movq %rbx, %rdi
movq %r13, %rsi
movq %rax, %rdx
callq 0x2060
movq 0x10(%rsp), %r13
leaq 0xc(%rsp), %rbx
jmp 0x314f
pushq $0xd
popq %rdi
pushq $0x1
popq %rsi
callq 0x22a0
callq 0x2530
testl %eax, %eax
movq 0x18(%rsp), %r14
js 0x34e4
jne 0x3535
callq 0x21f0
testl %eax, %eax
js 0x34e4
pushq $0x1
popq %rdi
pushq $0x1
popq %rsi
callq 0x22a0
callq 0x2530
testl %eax, %eax
js 0x34e4
jne 0x3535
movq 0x160d4(%rip), %rdi     # 0x194e8
callq 0x743b
movq %rax, 0x160c8(%rip)     # 0x194e8
movq 0x160c9(%rip), %rdi     # 0x194f0
callq 0x743b
movq %rax, 0x160bd(%rip)     # 0x194f0
movq 0x160be(%rip), %rdi     # 0x194f8
callq 0x743b
movq %rax, 0x160b2(%rip)     # 0x194f8
movq 0x160b3(%rip), %rdi     # 0x19500
callq 0x743b
movq %rax, 0x160a7(%rip)     # 0x19500
movl $0x7f8, %eax            # imm = 0x7F8
leaq 0x40(%rsp), %rsi
movq %rax, (%rsi)
movq %rax, 0x8(%rsi)
pushq $0x7
popq %rdi
callq 0x23c0
cmpl $-0x1, %eax
je 0x34f6
movq %r14, %rdi
callq 0x2d5c
movl (%r14), %edi
callq 0x2520
cmpl $-0x1, %eax
je 0x3583
movl (%r14), %edi
callq 0x2560
cmpl $-0x1, %eax
je 0x3583
leaq 0x161d0(%rip), %rbx     # 0x19678
movl 0x4(%r14), %eax
leal -0x1(%rax), %ecx
movl %ecx, 0x4(%r14)
cmpl $0x2, %eax
jl 0x34c3
callq 0x2530
movl %eax, (%rbx)
testl %eax, %eax
je 0x34a8
movl $0x3fc, %edi            # imm = 0x3FC
callq 0x2490
movl %eax, 0x12eb1(%rip)     # 0x16384
cmpl $-0x1, %eax
je 0x3577
movq %r14, %rdi
callq 0x2f83
addq $0x278, %rsp            # imm = 0x278
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x5c8a(%rip), %rdi      # 0x9187
callq 0x2460
jmp 0x3477
movq 0x18(%rsp), %rdi
callq 0x74cd
pushq $0x1
jmp 0x3523
callq 0x358b
xorl %edi, %edi
callq 0x24b0
pushq $0x3
popq %rdi
leaq 0x50(%rsp), %rsi
callq 0x2a2d
movl %eax, %edi
callq 0x24b0
leaq 0x15fac(%rip), %rdi     # 0x194e8
callq 0x7470
leaq 0x15fa8(%rip), %rdi     # 0x194f0
callq 0x7470
leaq 0x15fa4(%rip), %rdi     # 0x194f8
callq 0x7470
leaq 0x15fa0(%rip), %rdi     # 0x19500
callq 0x7470
movq %r14, %rdi
callq 0x74cd
movq %r14, %rdi
callq 0x2030
jmp 0x351a
leaq 0x5c13(%rip), %rdi      # 0x9191
callq 0x2460
pushq $0x1
popq %rdi
callq 0x24b0