// File: /workspace/github_c_makefile_star2_O0/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
subq $0x3160, %rsp           # imm = 0x3160
movl $0x0, -0x4(%rbp)
leaq -0x2ff0(%rbp), %rdi
xorl %esi, %esi
movl $0xfa0, %edx            # imm = 0xFA0
callq 0x1070
movl $0x0, -0x3064(%rbp)
leaq -0x30d0(%rbp), %rdi
xorl %esi, %esi
movl $0x64, %edx
callq 0x1070
movss 0x144a(%rip), %xmm0     # 0x3004
movss %xmm0, -0x30d4(%rbp)
xorps %xmm0, %xmm0
movss %xmm0, -0x30d8(%rbp)
xorps %xmm0, %xmm0
movss %xmm0, -0x30dc(%rbp)
xorps %xmm0, %xmm0
movss %xmm0, -0x30e0(%rbp)
leaq -0x38(%rbp), %rdi
xorl %esi, %esi
movl $0x30, %edx
callq 0x1070
movl $0x0, -0x34(%rbp)
movl $0x2, -0x30(%rbp)
movl $0x1, -0x38(%rbp)
leaq 0x142e(%rip), %rdi      # 0x303d
leaq 0x1431(%rip), %rsi      # 0x3047
leaq -0x38(%rbp), %rdx
leaq -0x40(%rbp), %rcx
callq 0x1150
movl %eax, -0x4c(%rbp)
cmpl $0x0, %eax
je 0x1c68
movq 0x33c6(%rip), %rax      # 0x4ff8
movq (%rax), %rax
movq %rax, -0x3108(%rbp)
movl -0x4c(%rbp), %edi
callq 0x1060
movq -0x3108(%rbp), %rdi
movq %rax, %rdx
leaq 0x13f8(%rip), %rsi      # 0x304d
movb $0x0, %al
callq 0x10b0
movl $0x1, -0x4(%rbp)
jmp 0x218c
movq -0x40(%rbp), %rax
movq %rax, -0x48(%rbp)
cmpq $0x0, -0x48(%rbp)
je 0x1ce9
movq -0x48(%rbp), %rax
movl 0x4(%rax), %edi
movq -0x48(%rbp), %rax
movl 0x8(%rax), %esi
movq -0x48(%rbp), %rax
movl 0xc(%rax), %edx
callq 0x1170
movl %eax, -0x8(%rbp)
cmpl $-0x1, %eax
jne 0x1ca7
leaq 0x13be(%rip), %rdi      # 0x305e
callq 0x10f0
jmp 0x1cdb
movl -0x8(%rbp), %edi
movq -0x48(%rbp), %rax
movq 0x18(%rax), %rsi
movq -0x48(%rbp), %rax
movl 0x10(%rax), %edx
callq 0x10e0
cmpl $-0x1, %eax
jne 0x1cd9
movl -0x8(%rbp), %edi
callq 0x1090
leaq 0x139b(%rip), %rdi      # 0x306d
callq 0x10f0
jmp 0x1cdb
jmp 0x1ce9
movq -0x48(%rbp), %rax
movq 0x28(%rax), %rax
movq %rax, -0x48(%rbp)
jmp 0x1c70
cmpq $0x0, -0x48(%rbp)
jne 0x1d14
movq 0x3301(%rip), %rax      # 0x4ff8
movq (%rax), %rdi
leaq 0x1379(%rip), %rsi      # 0x307a
movb $0x0, %al
callq 0x10b0
movl $0x2, -0x4(%rbp)
jmp 0x218c
movq -0x40(%rbp), %rdi
callq 0x1160
movl $0x80, -0xd4(%rbp)
leaq 0x136b(%rip), %rdi      # 0x3099
leaq 0x1312(%rip), %rsi      # 0x3047
movb $0x0, %al
callq 0x1050
movq 0x3295(%rip), %rax      # 0x4fd8
movq (%rax), %rdi
callq 0x10c0
movl -0x8(%rbp), %edi
leaq -0x10b0(%rbp), %rsi
movl $0xf9f, %edx            # imm = 0xF9F
xorl %ecx, %ecx
leaq -0xd0(%rbp), %r8
leaq -0xd4(%rbp), %r9
callq 0x10d0
movl %eax, -0x50(%rbp)
cmpl $-0x1, %eax
jne 0x1d8d
leaq 0x1350(%rip), %rdi      # 0x30ce
callq 0x10f0
movl $0x1, %edi
callq 0x1140
movslq -0x50(%rbp), %rax
movb $0x0, -0x10b0(%rbp,%rax)
leaq -0x2ff0(%rbp), %rdi
xorl %esi, %esi
movl $0xfa0, %edx            # imm = 0xFA0
callq 0x1070
movl $0x0, -0x30e4(%rbp)
cmpl $0xf, -0x30e4(%rbp)
jge 0x1de2
movslq -0x30e4(%rbp), %rax
movl $0xffffffff, -0x3060(%rbp,%rax,4) # imm = 0xFFFFFFFF
movl -0x30e4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x30e4(%rbp)
jmp 0x1db6
leaq -0x3020(%rbp), %rdi
leaq -0x10b0(%rbp), %rsi
leaq -0x2ff0(%rbp), %rdx
leaq -0x3060(%rbp), %rcx
callq 0x1330
movl %eax, -0x3064(%rbp)
leaq 0x12c7(%rip), %rdi      # 0x30d7
xorl %eax, %eax
movb %al, -0x3151(%rbp)
callq 0x1050
movb -0x3151(%rbp), %al
movq -0x3000(%rbp), %rsi
leaq 0x12d7(%rip), %rdi      # 0x3108
callq 0x1050
movb -0x3151(%rbp), %al
movq -0x2ff8(%rbp), %rsi
leaq 0x12dd(%rip), %rdi      # 0x3127
callq 0x1050
movb -0x3151(%rbp), %al
movq -0x3008(%rbp), %rsi
leaq 0x12e3(%rip), %rdi      # 0x3146
callq 0x1050
movb -0x3151(%rbp), %al
movq -0x3020(%rbp), %rsi
movq -0x3018(%rbp), %rdx
leaq 0x12d2(%rip), %rdi      # 0x3155
callq 0x1050
movl -0x3064(%rbp), %eax
movl %eax, %ecx
movq %rcx, %rax
movq %rsp, %rdx
movq %rdx, -0x30f0(%rbp)
movq %rcx, %rdx
imulq %rdx, %rdx
leaq 0xf(,%rdx,4), %rdx
andq $-0x10, %rdx
movq %rsp, %rdi
subq %rdx, %rdi
movq %rdi, -0x3130(%rbp)
movq %rdi, %rsp
movq %rcx, -0x30f8(%rbp)
movq %rax, -0x3100(%rbp)
movl -0x3064(%rbp), %eax
imull -0x3064(%rbp), %eax
movslq %eax, %rdx
shlq $0x2, %rdx
xorl %esi, %esi
callq 0x1070
movq -0x3130(%rbp), %rsi
movl -0x3064(%rbp), %edi
leaq -0x3060(%rbp), %rdx
leaq -0x2ff0(%rbp), %rcx
callq 0x1550
leaq -0x3060(%rbp), %rax
movq %rax, -0x3150(%rbp)
movl -0x3064(%rbp), %eax
movl %eax, -0x3144(%rbp)
movq -0x3020(%rbp), %rdi
callq 0x1110
movq -0x3150(%rbp), %rdi
movl -0x3144(%rbp), %esi
movl %eax, %edx
callq 0x1500
movl %eax, -0x3068(%rbp)
leaq -0x3060(%rbp), %rax
movq %rax, -0x3140(%rbp)
movl -0x3064(%rbp), %eax
movl %eax, -0x3134(%rbp)
movq -0x3018(%rbp), %rdi
callq 0x1110
movq -0x3140(%rbp), %rdi
movl -0x3134(%rbp), %esi
movl %eax, %edx
callq 0x1500
movq -0x3130(%rbp), %rsi
movl %eax, -0x306c(%rbp)
movl -0x3064(%rbp), %edi
movl -0x3068(%rbp), %edx
movl -0x306c(%rbp), %ecx
leaq -0x30d0(%rbp), %r8
leaq -0x3060(%rbp), %r9
callq 0x1930
movss %xmm0, -0x30d4(%rbp)
movq -0x3010(%rbp), %rdi
callq 0x1030
movsd %xmm0, -0x3128(%rbp)
movq -0x2ff8(%rbp), %rdi
callq 0x1030
movaps %xmm0, %xmm1
movsd -0x3128(%rbp), %xmm0
divsd %xmm1, %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, -0x30d8(%rbp)
movss -0x30d4(%rbp), %xmm0
cvtss2sd %xmm0, %xmm0
movsd %xmm0, -0x3120(%rbp)
movq -0x3000(%rbp), %rdi
callq 0x1030
movaps %xmm0, %xmm1
movsd -0x3120(%rbp), %xmm0
divsd %xmm1, %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, -0x30dc(%rbp)
movss -0x30d8(%rbp), %xmm0
addss -0x30dc(%rbp), %xmm0
movss %xmm0, -0x30e0(%rbp)
leaq 0x112b(%rip), %rdi      # 0x317d
movb $0x0, %al
callq 0x1050
leaq -0x30d0(%rbp), %rsi
leaq 0x1143(%rip), %rdi      # 0x31aa
movb $0x0, %al
callq 0x1050
movss -0x30d4(%rbp), %xmm0
cvtss2sd %xmm0, %xmm0
leaq 0x113c(%rip), %rdi      # 0x31bd
movb $0x1, %al
callq 0x1050
movss -0x30d8(%rbp), %xmm0
cvtss2sd %xmm0, %xmm0
leaq 0x113b(%rip), %rdi      # 0x31d6
movb $0x1, %al
callq 0x1050
movss -0x30dc(%rbp), %xmm0
cvtss2sd %xmm0, %xmm0
leaq 0x113b(%rip), %rdi      # 0x31f0
movb $0x1, %al
callq 0x1050
leaq -0x2050(%rbp), %rdi
movss -0x30d4(%rbp), %xmm0
cvtss2sd %xmm0, %xmm0
movss -0x30d8(%rbp), %xmm1
cvtss2sd %xmm1, %xmm1
movss -0x30dc(%rbp), %xmm2
cvtss2sd %xmm2, %xmm2
movss -0x30e0(%rbp), %xmm3
cvtss2sd %xmm3, %xmm3
leaq -0x30d0(%rbp), %rdx
leaq 0x1108(%rip), %rsi      # 0x3209
movb $0x4, %al
callq 0x1130
movl -0x8(%rbp), %eax
movl %eax, -0x3114(%rbp)
leaq -0x2050(%rbp), %rax
movq %rax, -0x3110(%rbp)
leaq -0x2050(%rbp), %rdi
callq 0x1040
movl -0x3114(%rbp), %edi
movq -0x3110(%rbp), %rsi
movq %rax, %rdx
movl -0xd4(%rbp), %r9d
xorl %ecx, %ecx
leaq -0xd0(%rbp), %r8
callq 0x1080
movl %eax, -0x50(%rbp)
cmpl $-0x1, -0x50(%rbp)
jne 0x216f
leaq 0x10c0(%rip), %rdi      # 0x3220
callq 0x10f0
movl $0x1, %edi
callq 0x1140
leaq 0x10bb(%rip), %rdi      # 0x3231
movb $0x0, %al
callq 0x1050
movq -0x30f0(%rbp), %rax
movq %rax, %rsp
jmp 0x1d4b
movl -0x4(%rbp), %eax
movq %rbp, %rsp
popq %rbp
retq