// File: /workspace/github_c_makefile_star2_O3/MAGI003769[P]EE450-Socket-Project/serverC.c
// Function: main
int main(void) {
    int sockfd;
    struct addrinfo hints, *servinfo, *p;
    int rv;
    int numbytes;
    struct sockaddr_storage their_addr;
    socklen_t addr_len;
    char s[INET6_ADDRSTRLEN];

    char data[MAXBUFLEN]; // 
    char buf[MAXBUFLEN];  // 
    char edges[MAXBUFLEN] = "";
    char *args[6];  // {<source ID>, <tarrget ID>, <file size>, <MAP ID>, <Prop speed>, <Trans speed>}

    int vtx_set[MAXNUMVERTICES];
    // set all vertex initialed as -1 to prevent the 0-initialization have crash for vertex id 0
    int vtx_num = 0;
    int src_idx, target_idx;
    char ans_path[100] = "";
    float shortest_dist = FLT_MAX;
    float trans_delay = 0.0;
    float prop_delay = 0.0;
    float total_delay = 0.0;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_DGRAM;
    hints.ai_flags = AI_PASSIVE;

    // get information of the backend server itself with MYPORT
    if((rv = getaddrinfo(IPADDRESS, MYPORT, &hints, &servinfo)) != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
        return 1;
    }

    // loop through all the results and make a socket
    for(p = servinfo; p != NULL; p = p->ai_next) {
        if((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
            perror("server: socket");
            continue;
        }

        if(bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
            close(sockfd);
            perror("server: bind");
            continue;
        }
        break;
    }

    if(p == NULL) {
        fprintf(stderr, "talker: failed to bind socket\n");
        return 2;
    }

    freeaddrinfo(servinfo);

    addr_len = sizeof their_addr;
    
    printf("The Server C is up and running using UDP on port %s\n", MYPORT);
    fflush(stdout);

    while(1) {
        if((numbytes = recvfrom(sockfd, data, MAXBUFLEN-1, 0,
            (struct sockaddr *)&their_addr, &addr_len)) == -1) {
            perror("recvfrom");
            exit(1);
        }
        data[numbytes] = '\0';
        // printf("debug: server-C received %d bytes from AWS\n", numbytes);
        // printf("debug: server-C received %s bytes from AWS\n", data);

        // read file and search the map_id
        //memset(&buf, 0, sizeof buf);
        memset(&edges, 0, sizeof edges);   // REMEBER to flush the edges buffer !!!
        for(int i = 0; i < MAXNUMVERTICES; i++) { // REMEBER to reset the vtx_set for new query
            vtx_set[i] = -1;
        }
        vtx_num = parse_data2(args, data, edges, vtx_set);
        // printf("debug: the number of vertices in map is %d\n", vtx_num);
        // for(int i = 0; i < MAXNUMVERTICES; i++) {
        //     printf("%d\t", vtx_set[i]);
        // }
        // printf("\n");
        // printf("debug: the length of edges in map is %lu\n", strlen(edges));
        // printf("debug: Edges:\n %s\n", edges);

        printf("The Server C has received data for calculation:\n");
        printf("* Propagation speed: %s km/s;\n", args[4]);
        printf("* Transmission speed %s KB/s;\n", args[5]);
        printf("* map ID: %s;\n", args[3]);
        printf("* Source ID: %s    Destination ID: %s;\n", args[0], args[1]);

        // printf("debug: vtx_set\n");
        // for(int i = 0; i < vtx_num; i++) {
        //     printf("%d\t", vtx_set[i]);
        // }
        // printf("\n");

        // Construct graph represents by a matrix initialized 0
        float G[vtx_num][vtx_num];
        memset(G, 0, vtx_num * vtx_num * sizeof(float));
        add_edges(vtx_num, G, vtx_set, edges);

        // Convert vertex IDs to index in graph matrix and find the shortest path
        src_idx = get_index(vtx_set, vtx_num, atoi(args[0]));
        target_idx = get_index(vtx_set, vtx_num, atoi(args[1]));
        shortest_dist = dijkstra(vtx_num, G, src_idx, target_idx, ans_path, vtx_set);

        // calculate delays
        trans_delay = atof(args[2]) / atof(args[5]);
        prop_delay = shortest_dist / atof(args[4]);
        total_delay = trans_delay + prop_delay;

        // printf("debug: The vertex set: \n");
        // for(int i = 0; i < MAXNUMVERTICES; i++) {
        //     printf("%d\t", get_index(vtx_set, vtx_num, vtx_set[i]));
        // }
        // printf("\n");
        // for(int i = 0; i < MAXNUMVERTICES; i++) {
        //     printf("%d\t", vtx_set[i]);
        // }
        // printf("\n");

        printf("The Server C has finished the calculation: \n");
        printf("Shortest path: %s\n", ans_path);
        printf("Shortest distance: %.4f\n", shortest_dist);
        printf("Transmission delay: %.4f\n", trans_delay);
        printf("Propagation delay: %.4f\n", prop_delay);

        // printing adjacency matrix for debug
        // for(int i = 0; i < vtx_num; i++) {
        //     for(int j = 0; j < vtx_num; j++) {
        //         printf("%.2f\t", G[i][j]);
        //     }
        //     printf("\n");
        // }

        // write answers to buf[] to send back to
        sprintf(buf, "%.4f\n%.4f\n%.4f\n%.4f\n%s", shortest_dist, trans_delay, prop_delay, total_delay, ans_path);

        numbytes = sendto(sockfd, buf, strlen(buf), 0,
            (struct sockaddr *)&their_addr, addr_len);
        
        if(numbytes == -1) {
            perror("listener: sendto");
            exit(1);
        }

        printf("The Server C finished sening the output to AWS\n");
        
        //close(sockfd);
    }

    return 0;

}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x30b8, %rsp           # imm = 0x30B8
leaq -0x2140(%rbp), %rdi
movl $0xfa0, %edx            # imm = 0xFA0
xorl %esi, %esi
callq 0x1080
pxor %xmm0, %xmm0
movdqa %xmm0, -0x100(%rbp)
movdqa %xmm0, -0x110(%rbp)
movdqa %xmm0, -0x120(%rbp)
movdqa %xmm0, -0x130(%rbp)
movdqa %xmm0, -0x140(%rbp)
movdqa %xmm0, -0x150(%rbp)
movl $0x0, -0xf0(%rbp)
leaq -0x180(%rbp), %rdx
movdqa %xmm0, (%rdx)
movdqa %xmm0, 0x10(%rdx)
movdqa %xmm0, 0x20(%rdx)
movl $0x2, 0x8(%rdx)
movl $0x1, (%rdx)
leaq 0x628(%rip), %rdi       # 0x203b
leaq 0x62b(%rip), %rsi       # 0x2045
leaq -0x60(%rbp), %rcx
callq 0x1170
testl %eax, %eax
jne 0x1a8f
movq -0x60(%rbp), %rbx
testq %rbx, %rbx
je 0x1a83
leaq 0x625(%rip), %r14       # 0x205c
leaq 0x62d(%rip), %r15       # 0x206b
movl 0x4(%rbx), %edi
movl 0x8(%rbx), %esi
movl 0xc(%rbx), %edx
callq 0x1190
movq %r14, %rdi
cmpl $-0x1, %eax
je 0x1a75
movl %eax, %r12d
movq 0x18(%rbx), %rsi
movl 0x10(%rbx), %edx
movl %eax, %edi
callq 0x10f0
cmpl $-0x1, %eax
jne 0x1aaa
movl %r12d, %edi
callq 0x10a0
movq %r15, %rdi
callq 0x1100
movq 0x28(%rbx), %rbx
testq %rbx, %rbx
jne 0x1a3e
callq 0x1210
movl $0x2, %eax
jmp 0x1a9b
movl %eax, %edi
callq 0x11b0
movl $0x1, %eax
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq -0x60(%rbp), %rdi
callq 0x1180
leaq -0x44(%rbp), %rbx
movl $0x80, (%rbx)
leaq 0x5d3(%rip), %rdi       # 0x2097
leaq 0x57a(%rip), %rsi       # 0x2045
xorl %eax, %eax
callq 0x1060
movq 0x24ff(%rip), %rax      # 0x3fd8
movq (%rax), %rdi
callq 0x10d0
leaq -0x11a0(%rbp), %rsi
leaq -0x200(%rbp), %r8
movl $0xf9f, %edx            # imm = 0xF9F
movl %r12d, -0x54(%rbp)
movl %r12d, %edi
xorl %ecx, %ecx
movq %rbx, %r9
callq 0x10e0
cmpl $-0x1, %eax
je 0x1e0d
leaq -0x11a0(%rbp), %rbx
cltq
movb $0x0, -0x11a0(%rbp,%rax)
movl $0xfa0, %edx            # imm = 0xFA0
leaq -0x2140(%rbp), %r14
movq %r14, %rdi
xorl %esi, %esi
callq 0x1080
pcmpeqd %xmm0, %xmm0
movdqa %xmm0, -0xb0(%rbp)
movdqa %xmm0, -0xa0(%rbp)
movdqa %xmm0, -0x90(%rbp)
movdqu %xmm0, -0x84(%rbp)
leaq -0xe0(%rbp), %rdi
movq %rbx, %rsi
movq %r14, %rdx
leaq -0xb0(%rbp), %rcx
callq 0x1386
movl %eax, %ebx
leaq 0x656(%rip), %rdi       # 0x21d1
callq 0x1030
movq -0xc0(%rbp), %rsi
leaq 0x547(%rip), %rdi       # 0x20d5
movq %rsi, -0x50(%rbp)
xorl %eax, %eax
callq 0x1060
movq -0xb8(%rbp), %rsi
leaq 0x54d(%rip), %rdi       # 0x20f4
movq %rsi, -0x40(%rbp)
xorl %eax, %eax
callq 0x1060
movq -0xc8(%rbp), %rsi
leaq 0x553(%rip), %rdi       # 0x2113
xorl %eax, %eax
callq 0x1060
movq -0xe0(%rbp), %r13
movq -0xd8(%rbp), %r14
leaq 0x546(%rip), %rdi       # 0x2122
movq %r13, %rsi
movq %r14, %rdx
xorl %eax, %eax
callq 0x1060
movq %rsp, -0x68(%rbp)
movl %ebx, %r15d
movq %r15, %rax
imulq %r15, %rax
leaq 0xf(,%rax,4), %rax
andq $-0x10, %rax
movq %rsp, %r12
subq %rax, %r12
movq %r12, %rsp
movl %ebx, %edx
imull %edx, %edx
shlq $0x2, %rdx
movq %r12, %rdi
xorl %esi, %esi
callq 0x1080
movl %ebx, %edi
movq %r12, %rsi
leaq -0xb0(%rbp), %rdx
leaq -0x2140(%rbp), %rcx
callq 0x14e0
movq %r13, %rdi
callq 0x1120
movl $0xffffffff, %r13d      # imm = 0xFFFFFFFF
testl %ebx, %ebx
jle 0x1c7e
xorl %ebx, %ebx
cmpl %eax, -0xb0(%rbp,%rbx,4)
je 0x1c61
incq %rbx
cmpq %rbx, %r15
jne 0x1c4b
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
movq %r14, %rdi
callq 0x1120
xorl %ecx, %ecx
cmpl %eax, -0xb0(%rbp,%rcx,4)
je 0x1c85
incq %rcx
cmpq %rcx, %r15
jne 0x1c6b
jmp 0x1c88
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
jmp 0x1c88
movl %ecx, %r13d
movl %r15d, %edi
movq %r12, %rsi
movl %ebx, %edx
movl %r13d, %ecx
leaq -0x150(%rbp), %rbx
movq %rbx, %r8
leaq -0xb0(%rbp), %r9
callq 0x17ed
movd %xmm0, -0x38(%rbp)
movq -0xd0(%rbp), %rdi
callq 0x1040
movq %xmm0, -0x30(%rbp)
movq -0x40(%rbp), %rdi
callq 0x1040
movsd -0x30(%rbp), %xmm1
divsd %xmm0, %xmm1
xorps %xmm0, %xmm0
cvtsd2ss %xmm1, %xmm0
movss %xmm0, -0x30(%rbp)
xorps %xmm0, %xmm0
cvtss2sd -0x38(%rbp), %xmm0
movsd %xmm0, -0x40(%rbp)
movq -0x50(%rbp), %rdi
callq 0x1040
movsd -0x40(%rbp), %xmm1
divsd %xmm0, %xmm1
cvtsd2ss %xmm1, %xmm1
movss %xmm1, -0x38(%rbp)
movss -0x30(%rbp), %xmm0
addss %xmm1, %xmm0
movss %xmm0, -0x50(%rbp)
leaq 0x4e7(%rip), %rdi       # 0x2201
callq 0x1030
leaq 0x424(%rip), %rdi       # 0x214a
movq %rbx, %rsi
xorl %eax, %eax
callq 0x1060
leaq 0x426(%rip), %rdi       # 0x215d
movsd -0x40(%rbp), %xmm0
movb $0x1, %al
callq 0x1060
xorps %xmm0, %xmm0
cvtss2sd -0x30(%rbp), %xmm0
movsd %xmm0, -0x30(%rbp)
leaq 0x41f(%rip), %rdi       # 0x2176
movb $0x1, %al
callq 0x1060
xorps %xmm0, %xmm0
cvtss2sd -0x38(%rbp), %xmm0
movsd %xmm0, -0x38(%rbp)
leaq 0x41e(%rip), %rdi       # 0x2190
movb $0x1, %al
callq 0x1060
cvtss2sd -0x50(%rbp), %xmm3
leaq -0x30e0(%rbp), %r14
movq %r14, %rdi
leaq 0x41a(%rip), %rsi       # 0x21a9
movq -0x40(%rbp), %xmm0
movsd -0x30(%rbp), %xmm1
movsd -0x38(%rbp), %xmm2
movq %rbx, %rdx
movb $0x4, %al
callq 0x1140
movq %r14, %rdi
callq 0x1050
movl -0x44(%rbp), %r9d
movl -0x54(%rbp), %ebx
movl %ebx, %edi
movq %r14, %rsi
movq %rax, %rdx
xorl %ecx, %ecx
leaq -0x200(%rbp), %r14
movq %r14, %r8
callq 0x1090
cmpl $-0x1, %eax
je 0x1e12
leaq 0x451(%rip), %rdi       # 0x222d
callq 0x1030
movq -0x68(%rbp), %rsp
movl $0xf9f, %edx            # imm = 0xF9F
movl %ebx, %edi
leaq -0x11a0(%rbp), %rbx
movq %rbx, %rsi
xorl %ecx, %ecx
movq %r14, %r8
leaq -0x44(%rbp), %r9
callq 0x10e0
cmpl $-0x1, %eax
jne 0x1b15
callq 0x11f8
callq 0x11e0