// File: brianbbsu[P]TCP-Ping/src/client.cpp
// Function: main
int main(int argc, char *argv[])
{
    int num, tout, twait;
    std::vector<std::string> target_strs;
    po::options_description desc, desc_all;
    desc.add_options()
    ("help,h", "Print help messages")
    ("num,n", po::value<int>(&num)->default_value(0), "Amount of packets to send to each target, 0 means keep sending messages until program close")
    ("timeout,t", po::value<int>(&tout)->default_value(1000), "Maximum millisecond(s) the client needs to wait for each response")
    ("wait,w", po::value<int>(&twait)->default_value(1000), "Millisecond(s) the client need to wait between each ping");
    desc_all.add(desc);
    desc_all.add_options()
    ("target", po::value<std::vector<std::string>>(&target_strs), "Target(s) in `host:port` form, host can be in hostname or ip");

    po::positional_options_description pos_desc;
    pos_desc.add("target", -1);

    po::variables_map vmap;
    try{
        po::store(po::command_line_parser(argc, argv).options(desc_all).positional(pos_desc).run(), vmap);
        if(vmap.count("help"))print_help(desc);
        po::notify(vmap);
        if(tout < 0)throw std::invalid_argument("timeout should not be negative");
        if(num < 0)throw std::invalid_argument("num should not be negative");
        if(twait < 0)throw std::invalid_argument("waiting time should not be negative");
        if(target_strs.size() == 0)throw std::invalid_argument("there should be at least one target");
    }catch(const std::exception &ex){
        logger::log_error("Failed to parse arguments: " + std::string(ex.what()) + "\n");
        print_help(desc);
    }

    for(auto &s:target_strs)targets.push_back(cmd_to_target(s));

    logger::log_info("== TCP Ping - Client - Made by Po-Hsuan Su (b08902107) ==");

    std::vector<std::thread> thread_v;

    // Start all thread
    for(int i = 0;i < targets.size();i ++)thread_v.emplace_back(pinger, std::ref(targets[i]), i + 1, num, tout, twait);
    
    struct sigaction sa;
    sa.sa_handler = finalize;
    sa.sa_flags = 0;
    sigemptyset(&sa.sa_mask);
    sigaction(SIGINT, &sa, NULL);

    // Wail all thread to finish
    for(auto &t:thread_v)t.join();

    finalize(0);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x6f0, %rsp            # imm = 0x6F0
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
leaq -0x38(%rbp), %rdi
callq 0xad60
movq 0x237c7(%rip), %rax     # 0x2cf70
movl (%rax), %esi
movl %esi, %edx
shrl %edx
leaq -0xb8(%rbp), %rdi
callq 0x7890
jmp 0x97bd
movq 0x237ac(%rip), %rax     # 0x2cf70
movl (%rax), %esi
movl %esi, %edx
shrl %edx
leaq -0x148(%rbp), %rdi
callq 0x7890
jmp 0x97d8
leaq -0xb8(%rbp), %rdi
callq 0x7520
movq %rax, -0x628(%rbp)
jmp 0x97ed
movq -0x628(%rbp), %rax
movq %rax, -0x150(%rbp)
leaq 0x14acf(%rip), %rsi     # 0x1e2d1
leaq 0x14acf(%rip), %rdx     # 0x1e2d8
leaq -0x150(%rbp), %rdi
callq 0x77f0
movq %rax, -0x630(%rbp)
jmp 0x981e
leaq -0x14(%rbp), %rdi
callq 0xad80
movq %rax, -0x638(%rbp)
jmp 0x9830
movq -0x638(%rbp), %rdi
movl $0x0, -0x154(%rbp)
leaq -0x154(%rbp), %rsi
callq 0xade0
movq %rax, -0x640(%rbp)
jmp 0x9856
movq -0x640(%rbp), %rdx
movq -0x630(%rbp), %rdi
leaq 0x14a81(%rip), %rsi     # 0x1e2ec
leaq 0x14a80(%rip), %rcx     # 0x1e2f2
callq 0x7840
movq %rax, -0x648(%rbp)
jmp 0x9880
leaq -0x18(%rbp), %rdi
callq 0xad80
movq %rax, -0x650(%rbp)
jmp 0x9892
movq -0x650(%rbp), %rdi
movl $0x3e8, -0x158(%rbp)    # imm = 0x3E8
leaq -0x158(%rbp), %rsi
callq 0xade0
movq %rax, -0x658(%rbp)
jmp 0x98b8
movq -0x658(%rbp), %rdx
movq -0x648(%rbp), %rdi
leaq 0x14a81(%rip), %rsi     # 0x1e34e
leaq 0x14a84(%rip), %rcx     # 0x1e358
callq 0x7840
movq %rax, -0x660(%rbp)
jmp 0x98e2
leaq -0x1c(%rbp), %rdi
callq 0xad80
movq %rax, -0x668(%rbp)
jmp 0x98f4
movq -0x668(%rbp), %rdi
movl $0x3e8, -0x15c(%rbp)    # imm = 0x3E8
leaq -0x15c(%rbp), %rsi
callq 0xade0
movq %rax, -0x670(%rbp)
jmp 0x991a
movq -0x670(%rbp), %rdx
movq -0x660(%rbp), %rdi
leaq 0x14a6b(%rip), %rsi     # 0x1e39a
leaq 0x14a6b(%rip), %rcx     # 0x1e3a1
callq 0x7840
jmp 0x993d
leaq -0x148(%rbp), %rdi
leaq -0xb8(%rbp), %rsi
callq 0x7460
jmp 0x9952
leaq -0x148(%rbp), %rdi
callq 0x7520
movq %rax, -0x678(%rbp)
jmp 0x9967
movq -0x678(%rbp), %rax
movq %rax, -0x168(%rbp)
leaq -0x38(%rbp), %rdi
callq 0xae50
movq %rax, -0x680(%rbp)
jmp 0x9987
movq -0x680(%rbp), %rdx
leaq 0x14b02(%rip), %rsi     # 0x1e497
leaq 0x14a3e(%rip), %rcx     # 0x1e3da
leaq -0x168(%rbp), %rdi
callq 0x7840
jmp 0x99aa
leaq -0x1a0(%rbp), %rdi
callq 0x75e0
jmp 0x99b8
leaq 0x14ad8(%rip), %rsi     # 0x1e497
leaq -0x1a0(%rbp), %rdi
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
callq 0x74c0
jmp 0x99d2
leaq -0x240(%rbp), %rdi
callq 0x71a0
jmp 0x99e0
movl -0x8(%rbp), %esi
movq -0x10(%rbp), %rdx
leaq -0x2e0(%rbp), %rdi
callq 0xaeb0
jmp 0x99f5
leaq -0x2e0(%rbp), %rdi
leaq -0x148(%rbp), %rsi
callq 0xafd0
movq %rax, -0x688(%rbp)
jmp 0x9a11
movq -0x688(%rbp), %rdi
leaq -0x1a0(%rbp), %rsi
callq 0xb010
movq %rax, -0x690(%rbp)
jmp 0x9a2d
movq -0x690(%rbp), %rsi
leaq -0x268(%rbp), %rdi
callq 0xb040
jmp 0x9a42
leaq -0x268(%rbp), %rdi
leaq -0x240(%rbp), %rsi
xorl %edx, %edx
callq 0x7790
jmp 0x9a59
leaq -0x268(%rbp), %rdi
callq 0xb100
leaq -0x2e0(%rbp), %rdi
callq 0xb120
leaq -0x230(%rbp), %rax
movq %rax, -0x6a0(%rbp)
leaq -0x301(%rbp), %rdi
movq %rdi, -0x698(%rbp)
callq 0x77c0
movq -0x698(%rbp), %rdx
leaq 0x14977(%rip), %rsi     # 0x1e417
leaq -0x300(%rbp), %rdi
callq 0xa3f0
jmp 0x9aae
movq -0x6a0(%rbp), %rdi
leaq -0x300(%rbp), %rsi
callq 0xb140
movq %rax, -0x6a8(%rbp)
jmp 0x9aca
leaq -0x300(%rbp), %rdi
callq 0x78b8
leaq -0x301(%rbp), %rdi
callq 0x74b0
movq -0x6a8(%rbp), %rax
cmpq $0x0, %rax
je 0x9c43
leaq -0x388(%rbp), %rdi
leaq -0xb8(%rbp), %rsi
callq 0xb1a0
jmp 0x9b08
leaq -0x388(%rbp), %rdi
callq 0x9380
jmp 0x9b16
leaq -0x388(%rbp), %rdi
callq 0xb280
jmp 0x9c43
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
jmp 0xa3d3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
jmp 0xa3c7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
jmp 0xa3bb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
jmp 0xa3af
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
jmp 0x9e0a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
jmp 0x9bcc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
leaq -0x268(%rbp), %rdi
callq 0xb100
leaq -0x2e0(%rbp), %rdi
callq 0xb120
jmp 0x9e0a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
jmp 0x9c0f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
leaq -0x300(%rbp), %rdi
callq 0x78b8
leaq -0x301(%rbp), %rdi
callq 0x74b0
jmp 0x9e0a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
leaq -0x388(%rbp), %rdi
callq 0xb280
jmp 0x9e0a
leaq -0x240(%rbp), %rdi
callq 0x7230
jmp 0x9c51
cmpl $0x0, -0x18(%rbp)
jge 0x9cbe
movl $0x10, %edi
callq 0x71f0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x6b0(%rbp)
leaq 0x147a7(%rip), %rsi     # 0x1e41c
callq 0x7810
jmp 0x9c7c
movq -0x6b0(%rbp), %rdi
movq 0x23356(%rip), %rsi     # 0x2cfe0
movq 0x23337(%rip), %rdx     # 0x2cfc8
callq 0x7760
jmp 0xa3f0
movq -0x6b0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
callq 0x7330
jmp 0x9e0a
cmpl $0x0, -0x14(%rbp)
jge 0x9d2b
movl $0x10, %edi
callq 0x71f0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x6b8(%rbp)
leaq 0x14759(%rip), %rsi     # 0x1e43b
callq 0x7810
jmp 0x9ce9
movq -0x6b8(%rbp), %rdi
movq 0x232e9(%rip), %rsi     # 0x2cfe0
movq 0x232ca(%rip), %rdx     # 0x2cfc8
callq 0x7760
jmp 0xa3f0
movq -0x6b8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
callq 0x7330
jmp 0x9e0a
cmpl $0x0, -0x1c(%rbp)
jge 0x9d95
movl $0x10, %edi
callq 0x71f0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x6c0(%rbp)
leaq 0x14707(%rip), %rsi     # 0x1e456
callq 0x7810
jmp 0x9d56
movq -0x6c0(%rbp), %rdi
movq 0x2327c(%rip), %rsi     # 0x2cfe0
movq 0x2325d(%rip), %rdx     # 0x2cfc8
callq 0x7760
jmp 0xa3f0
movq -0x6c0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
callq 0x7330
jmp 0x9e0a
leaq -0x38(%rbp), %rdi
callq 0xb2d0
cmpq $0x0, %rax
jne 0x9ff1
movl $0x10, %edi
callq 0x71f0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x6c8(%rbp)
leaq 0x146b4(%rip), %rsi     # 0x1e47a
callq 0x7810
jmp 0x9dcd
movq -0x6c8(%rbp), %rdi
movq 0x23205(%rip), %rsi     # 0x2cfe0
movq 0x231e6(%rip), %rdx     # 0x2cfc8
callq 0x7760
jmp 0xa3f0
movq -0x6c8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
callq 0x7330
movl -0xc4(%rbp), %eax
movl $0x1, %ecx
cmpl %ecx, %eax
jne 0xa3a3
movq -0xc0(%rbp), %rdi
callq 0x7180
movq %rax, -0x390(%rbp)
movq -0x390(%rbp), %rdi
movq (%rdi), %rax
movq 0x10(%rax), %rax
callq *%rax
movq %rax, -0x6d8(%rbp)
leaq -0x3f1(%rbp), %rdi
movq %rdi, -0x6d0(%rbp)
callq 0x77c0
movq -0x6d8(%rbp), %rsi
movq -0x6d0(%rbp), %rdx
leaq -0x3f0(%rbp), %rdi
callq 0xa3f0
jmp 0x9e76
leaq 0x14621(%rip), %rsi     # 0x1e49e
leaq -0x3d0(%rbp), %rdi
leaq -0x3f0(%rbp), %rdx
callq 0xa690
jmp 0x9e92
leaq 0x14372(%rip), %rdx     # 0x1e20b
leaq -0x3b0(%rbp), %rdi
leaq -0x3d0(%rbp), %rsi
callq 0xa4a0
jmp 0x9eae
leaq -0x3b0(%rbp), %rdi
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
callq 0x1d310
jmp 0x9ec1
leaq -0x3b0(%rbp), %rdi
callq 0x78b8
leaq -0x3d0(%rbp), %rdi
callq 0x78b8
leaq -0x3f0(%rbp), %rdi
callq 0x78b8
leaq -0x3f1(%rbp), %rdi
callq 0x74b0
leaq -0x478(%rbp), %rdi
leaq -0xb8(%rbp), %rsi
callq 0xb1a0
jmp 0x9f06
leaq -0x478(%rbp), %rdi
callq 0x9380
jmp 0x9f14
leaq -0x478(%rbp), %rdi
callq 0xb280
callq 0x7700
jmp 0x9f27
jmp 0x9f29
leaq -0x38(%rbp), %rax
movq %rax, -0x480(%rbp)
movq -0x480(%rbp), %rdi
callq 0xb2f0
movq %rax, -0x488(%rbp)
movq -0x480(%rbp), %rdi
callq 0xb320
movq %rax, -0x490(%rbp)
leaq -0x488(%rbp), %rdi
leaq -0x490(%rbp), %rsi
callq 0xb350
testb $0x1, %al
jne 0x9f76
jmp 0xa110
leaq -0x488(%rbp), %rdi
callq 0xb390
movq %rax, -0x498(%rbp)
movq -0x498(%rbp), %rsi
leaq -0x510(%rbp), %rdi
callq 0x71b0
jmp 0x9f9e
leaq -0x4f0(%rbp), %rdi
leaq -0x510(%rbp), %rsi
callq 0x81c0
jmp 0x9fb3
leaq 0x235b6(%rip), %rdi     # 0x2d570
leaq -0x4f0(%rbp), %rsi
callq 0xb3b0
jmp 0x9fc8
leaq -0x4f0(%rbp), %rdi
callq 0xb3e0
leaq -0x510(%rbp), %rdi
callq 0x78b8
leaq -0x488(%rbp), %rdi
callq 0xb410
jmp 0x9f5a
jmp 0x9f29
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
jmp 0xa068
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
jmp 0xa05c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
jmp 0xa050
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
leaq -0x3b0(%rbp), %rdi
callq 0x78b8
leaq -0x3d0(%rbp), %rdi
callq 0x78b8
leaq -0x3f0(%rbp), %rdi
callq 0x78b8
leaq -0x3f1(%rbp), %rdi
callq 0x74b0
jmp 0xa0c1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
jmp 0xa0c1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
leaq -0x478(%rbp), %rdi
callq 0xb280
jmp 0xa0c1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
jmp 0xa3a3
callq 0x7700
jmp 0xa0c8
jmp 0xa3a3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
jmp 0xa0ff
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
leaq -0x4f0(%rbp), %rdi
callq 0xb3e0
leaq -0x510(%rbp), %rdi
callq 0x78b8
jmp 0xa3a3
leaq -0x531(%rbp), %rdi
movq %rdi, -0x6e0(%rbp)
callq 0x77c0
movq -0x6e0(%rbp), %rdx
leaq 0x14389(%rip), %rsi     # 0x1e4ba
leaq -0x530(%rbp), %rdi
callq 0xa3f0
jmp 0xa13f
leaq -0x530(%rbp), %rdi
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
callq 0x1d1c0
jmp 0xa152
leaq -0x530(%rbp), %rdi
callq 0x78b8
leaq -0x531(%rbp), %rdi
callq 0x74b0
leaq -0x550(%rbp), %rdi
callq 0xb430
movl $0x0, -0x554(%rbp)
movslq -0x554(%rbp), %rax
movq %rax, -0x6e8(%rbp)
leaq 0x233db(%rip), %rdi     # 0x2d570
callq 0xb450
movq %rax, %rcx
movq -0x6e8(%rbp), %rax
cmpq %rcx, %rax
jae 0xa28e
movslq -0x554(%rbp), %rsi
leaq 0x233b5(%rip), %rdi     # 0x2d570
callq 0xb570
movq %rax, %rdi
callq 0xb540
movq %rax, -0x560(%rbp)
movl -0x554(%rbp), %eax
incl %eax
movl %eax, -0x564(%rbp)
movq %rsp, %rax
leaq -0x1c(%rbp), %rcx
movq %rcx, (%rax)
leaq -0x198e(%rip), %rsi     # 0x8860
leaq -0x550(%rbp), %rdi
leaq -0x560(%rbp), %rdx
leaq -0x564(%rbp), %rcx
leaq -0x14(%rbp), %r8
leaq -0x18(%rbp), %r9
callq 0xb480
jmp 0xa212
jmp 0xa214
movl -0x554(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x554(%rbp)
jmp 0xa180
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
jmp 0xa25a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
leaq -0x530(%rbp), %rdi
callq 0x78b8
leaq -0x531(%rbp), %rdi
callq 0x74b0
jmp 0xa3a3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
leaq -0x550(%rbp), %rdi
callq 0xb670
jmp 0xa3a3
leaq -0xe85(%rip), %rax      # 0x9410
movq %rax, -0x600(%rbp)
movl $0x0, -0x578(%rbp)
leaq -0x600(%rbp), %rdi
addq $0x8, %rdi
callq 0x7570
movl $0x2, %edi
leaq -0x600(%rbp), %rsi
xorl %eax, %eax
movl %eax, %edx
callq 0x7580
leaq -0x550(%rbp), %rax
movq %rax, -0x608(%rbp)
movq -0x608(%rbp), %rdi
callq 0xb590
movq %rax, -0x610(%rbp)
movq -0x608(%rbp), %rdi
callq 0xb5c0
movq %rax, -0x618(%rbp)
leaq -0x610(%rbp), %rdi
leaq -0x618(%rbp), %rsi
callq 0xb5f0
testb $0x1, %al
jne 0xa318
jmp 0xa349
leaq -0x610(%rbp), %rdi
callq 0xb630
movq %rax, -0x620(%rbp)
movq -0x620(%rbp), %rdi
callq 0x7750
jmp 0xa339
jmp 0xa33b
leaq -0x610(%rbp), %rdi
callq 0xb650
jmp 0xa2ff
xorl %edi, %edi
callq 0x9410
jmp 0xa352
leaq -0x550(%rbp), %rdi
callq 0xb670
leaq -0x240(%rbp), %rdi
callq 0xb6d0
leaq -0x1a0(%rbp), %rdi
callq 0xb730
leaq -0x148(%rbp), %rdi
callq 0xb280
leaq -0xb8(%rbp), %rdi
callq 0xb280
leaq -0x38(%rbp), %rdi
callq 0xb760
movl -0x4(%rbp), %eax
addq $0x6f0, %rsp            # imm = 0x6F0
popq %rbp
retq
leaq -0x240(%rbp), %rdi
callq 0xb6d0
leaq -0x1a0(%rbp), %rdi
callq 0xb730
leaq -0x148(%rbp), %rdi
callq 0xb280
leaq -0xb8(%rbp), %rdi
callq 0xb280
leaq -0x38(%rbp), %rdi
callq 0xb760
movq -0xc0(%rbp), %rdi
callq 0x77a0
movq %rax, %rdi
callq 0xa6e0