// File: /workspace/github_c_makefile_star2_O1/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 $0x268, %rsp            # imm = 0x268
movq %rsi, %r14
movl %edi, %ebp
xorl %eax, %eax
leaq 0x4(%rsp), %r15
movl %eax, (%r15)
leaq 0x150(%rsp), %rbx
movl $0x10e, %edx            # imm = 0x10E
movq %rbx, %rdi
xorl %esi, %esi
callq 0x21b0
leaq 0x40(%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 0x2dc0
movq %rbx, %rdi
callq 0x2140
movabsq $0x2e79786f7250432f, %rcx # imm = 0x2E79786F7250432F
movq %rcx, 0x150(%rsp,%rax)
movabsq $0x666e6f632e7978, %rcx # imm = 0x666E6F632E7978
movq %rcx, 0x155(%rsp,%rax)
movl $0xc0, %edi
callq 0x2320
movq %rax, %r13
movl $0xc0, %edx
movq %rax, %rdi
xorl %esi, %esi
callq 0x21b0
movq %rbx, %rdi
movq %r13, 0x8(%rsp)
movq %r13, %rsi
movq %r15, %r13
callq 0x79d8
leaq 0x16320(%rip), %rax     # 0x19654
xorl %ecx, %ecx
movl %ecx, (%rax)
movaps 0x5fa1(%rip), %xmm0     # 0x92e0
leaq 0x10(%rsp), %r15
movaps %xmm0, (%r15)
movw $0x3f, 0x10(%r15)
leaq 0x5cba(%rip), %rbx      # 0x9010
movl %ebp, %edi
movq %r14, %rsi
movq %r15, %rdx
leaq 0x8f5b(%rip), %rcx      # 0xc2c0
movq %r13, %r8
callq 0x2150
leal -0x63(%rax), %ecx
cmpl $0x11, %ecx
ja 0x3581
movslq (%rbx,%rcx,4), %rax
addq %rbx, %rax
jmpq *%rax
leaq 0x1614f(%rip), %rdi     # 0x194d8
callq 0x78b8
leaq 0x1614b(%rip), %rdi     # 0x194e0
callq 0x78b8
leaq 0x16147(%rip), %rdi     # 0x194e8
callq 0x78b8
leaq 0x16143(%rip), %rdi     # 0x194f0
callq 0x78b8
movq 0x8(%rsp), %r15
movq %r15, %rdi
callq 0x7939
movl $0xc0, %edx
movq %r15, %rdi
xorl %esi, %esi
callq 0x21b0
movq 0x8bfb(%rip), %rax      # 0xbfd0
movq (%rax), %rdi
movq %r15, %rsi
leaq 0x10(%rsp), %r15
callq 0x79d8
jmp 0x3356
movq 0x8bdf(%rip), %rax      # 0xbfd0
movq (%rax), %rdi
callq 0x2470
leaq 0x16130(%rip), %rcx     # 0x19530
movl %eax, (%rcx)
jmp 0x3356
movq 0x8bc2(%rip), %rax      # 0xbfd0
movq (%rax), %rdi
callq 0x2470
movl %eax, 0x15f50(%rip)     # 0x1936c
jmp 0x3356
movq 0x8ba8(%rip), %rax      # 0xbfd0
movq (%rax), %rdi
callq 0x2470
leaq 0x1621d(%rip), %rcx     # 0x19654
movl %eax, (%rcx)
jmp 0x3356
movq 0x8b8b(%rip), %rax      # 0xbfd0
movq (%rax), %r15
movq %r15, %rdi
movl $0x3a, %esi
callq 0x2160
testq %rax, %rax
je 0x3594
movq %rax, %r13
movq %rax, %rdx
subq %r15, %rdx
leaq 0x15f52(%rip), %rdi     # 0x193c0
movq %r15, %rsi
callq 0x2060
incq %r13
movq %r13, %rdi
callq 0x2470
movl %eax, 0x16049(%rip)     # 0x194d0
jmp 0x35ba
movq 0x8b3d(%rip), %rax      # 0xbfd0
movq (%rax), %r15
movq %r15, %rdi
movl $0x3a, %esi
callq 0x2160
testq %rax, %rax
je 0x359d
movq %rax, %r13
movq %rax, %rdx
subq %r15, %rdx
leaq 0x16084(%rip), %rdi     # 0x19540
movq %r15, %rsi
callq 0x2060
incq %r13
movq %r13, %rdi
callq 0x2470
leaq 0x1617a(%rip), %rcx     # 0x19650
movl %eax, (%rcx)
jmp 0x35ba
movq 0x8aec(%rip), %rax      # 0xbfd0
movq (%rax), %r15
movq %r15, %rdi
leaq 0x5c80(%rip), %rsi      # 0x9171
callq 0x2040
testl %eax, %eax
je 0x371b
movq %r15, %rdi
leaq 0x5c6e(%rip), %rsi      # 0x9176
callq 0x2040
testl %eax, %eax
je 0x371b
movq %r15, %rdi
leaq 0x5c5c(%rip), %rsi      # 0x917b
callq 0x2040
testl %eax, %eax
je 0x353b
movq %r15, %rdi
leaq 0x5c51(%rip), %rsi      # 0x9183
callq 0x2040
testl %eax, %eax
jne 0x3559
movl $0x1, %edi
movq %r12, %rsi
callq 0x2c00
movl $0x4, %edi
movq %r12, %rsi
callq 0x2c00
testl %eax, %eax
je 0x3548
movq 0x8a70(%rip), %rax      # 0xbfd0
movq (%rax), %rdi
leaq 0x5cac(%rip), %rsi      # 0x9216
callq 0x2040
testl %eax, %eax
leaq 0x10(%rsp), %r15
jne 0x3356
jmp 0x373d
cmpl $-0x1, %eax
je 0x35c9
cmpl $0x3f, %eax
jne 0x3356
jmp 0x3731
leaq 0x15e25(%rip), %r13     # 0x193c0
jmp 0x35a4
leaq 0x15f9c(%rip), %r13     # 0x19540
movq %r13, %rdi
callq 0x2140
movq %r13, %rdi
movq %r15, %rsi
movq %rax, %rdx
callq 0x2060
leaq 0x4(%rsp), %r13
leaq 0x10(%rsp), %r15
jmp 0x3356
movl $0x1, %esi
movl $0xd, %edi
callq 0x2290
callq 0x2520
testl %eax, %eax
movq 0x8(%rsp), %r14
js 0x36f8
jne 0x3753
callq 0x21f0
testl %eax, %eax
js 0x36f8
movl $0x1, %esi
movl $0x1, %edi
callq 0x2290
callq 0x2520
testl %eax, %eax
js 0x36f8
jne 0x3753
movq 0x15eb2(%rip), %rdi     # 0x194d8
callq 0x7887
movq %rax, 0x15ea6(%rip)     # 0x194d8
movq 0x15ea7(%rip), %rdi     # 0x194e0
callq 0x7887
movq %rax, 0x15e9b(%rip)     # 0x194e0
movq 0x15e9c(%rip), %rdi     # 0x194e8
callq 0x7887
movq %rax, 0x15e90(%rip)     # 0x194e8
movq 0x15e91(%rip), %rdi     # 0x194f0
callq 0x7887
movq %rax, 0x15e85(%rip)     # 0x194f0
movl $0x7f8, %eax            # imm = 0x7F8
leaq 0x30(%rsp), %rsi
movq %rax, (%rsi)
movq %rax, 0x8(%rsi)
movl $0x7, %edi
callq 0x23b0
cmpl $-0x1, %eax
je 0x370a
movq %r14, %rdi
callq 0x2f70
movl (%r14), %edi
callq 0x2510
cmpl $-0x1, %eax
je 0x3795
movl (%r14), %edi
callq 0x2550
cmpl $-0x1, %eax
je 0x3795
leaq 0x15fac(%rip), %rbx     # 0x19668
movl 0x4(%r14), %eax
leal -0x1(%rax), %ecx
movl %ecx, 0x4(%r14)
cmpl $0x2, %eax
jl 0x36d7
callq 0x2520
movl %eax, (%rbx)
testl %eax, %eax
je 0x36bc
movl $0x3fc, %edi            # imm = 0x3FC
callq 0x2480
movl %eax, 0x12c8d(%rip)     # 0x16374
cmpl $-0x1, %eax
je 0x379f
movq %r14, %rdi
callq 0x317d
addq $0x268, %rsp            # imm = 0x268
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x5a79(%rip), %rdi      # 0x918a
callq 0x2450
jmp 0x368b
movq 0x8(%rsp), %rdi
callq 0x7939
leaq 0x40(%rsp), %rsi
movl $0x1, %edi
jmp 0x3747
callq 0x2570
xorl %edi, %edi
callq 0x24a0
leaq 0x40(%rsp), %rsi
movl $0x3, %edi
callq 0x2c00
movl %eax, %edi
callq 0x24a0
leaq 0x15d7e(%rip), %rdi     # 0x194d8
callq 0x78b8
leaq 0x15d7a(%rip), %rdi     # 0x194e0
callq 0x78b8
leaq 0x15d76(%rip), %rdi     # 0x194e8
callq 0x78b8
leaq 0x15d72(%rip), %rdi     # 0x194f0
callq 0x78b8
movq %r14, %rdi
callq 0x7939
movq %r14, %rdi
callq 0x2030
jmp 0x3736
movl $0x1, %edi
callq 0x24a0
callq 0x267e