Advertisement
Guest User

server.c

a guest
Nov 27th, 2017
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.40 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <errno.h>
  6. #include <sys/types.h>
  7. #include <sys/socket.h>
  8. #include <netdb.h>
  9. #include <netinet/in.h>
  10. #include <arpa/inet.h>
  11. #include <sys/wait.h>
  12. #include <signal.h>
  13. #include <netdb.h>
  14. #include <pthread.h>
  15. #include <time.h>
  16. #define MAXBUF 1024
  17. #define numUsers 10
  18. #define packetSize 256
  19. #define payloadSize 248
  20. #define headerSize 8
  21.  
  22. int udpSocket = 0;
  23. int returnStatus = 0;
  24. int isAuthenticated = 0;
  25. int windowSize = 1;
  26. int fileSize = 0;
  27. int read_size = 0;
  28. int timeout = 10;
  29. int numRetransmitted = 0;
  30. int numAcksReceived = 0;
  31. int numNacksReceived = 0;
  32. socklen_t addrlen;
  33. struct sockaddr_in udpServer;
  34. struct sockaddr_in udpClient;
  35. FILE *userFP;
  36. FILE *clientFP;
  37. char buf[MAXBUF];
  38. char username[256] = "";
  39. char password[256] = "";
  40. char filename[256] = "";
  41. char packetBuffer[256] = "";
  42. char *dataBuffer = NULL;
  43. time_t **timerAckList;
  44. int *doNotSendList;
  45. pthread_t waitThread;
  46. void* param;
  47.  
  48. /* define a user */
  49. struct user {
  50.     char username[256];
  51.     char password[256];
  52. } users[numUsers];
  53.  
  54. void *waitForAck(void* param) {
  55.     while(1) {
  56.         char threadBuf[256] = "";
  57.         // printf("Listening....\n");
  58.         int threadReturnStatus = recvfrom(udpSocket, threadBuf, 256, 0, (struct sockaddr*)&udpClient, &addrlen);
  59.         if (threadReturnStatus == -1) {
  60.             fprintf(stderr, "Client connection error in waitForAck thread.\n");
  61.             continue;
  62.         }
  63.  
  64.         // parse response
  65.         int ackIndex = atoi(&threadBuf[3]);
  66.         printf("Received ACK at index %d!!!\n", ackIndex);
  67.         fflush(stdout);
  68.  
  69.         // set ACK
  70.         // timerAckList[ackIndex] = NULL;
  71.         doNotSendList[ackIndex] = 1;
  72.     }
  73.  
  74.     return NULL;
  75. }
  76. int main(int argc, char* argv[]) {
  77.  
  78.     /* check for the right number of arguments */
  79.     if (argc < 3) {
  80.         fprintf(stderr, "Usage: %s <port> <window size>\n", argv[0]);
  81.         exit(1);
  82.     }
  83.  
  84.     windowSize = atoi(argv[2]);
  85.  
  86.     /* create a socket */
  87.     udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
  88.     if (udpSocket == -1) {
  89.         fprintf(stderr, "Could not create a socket!\n");
  90.         exit(1);
  91.     } else {
  92.         printf("Socket created.\n");
  93.     }
  94.  
  95.     /* set up the server address and port */
  96.     /* use INADDR_ANY to bind to all local addresses */
  97.     udpServer.sin_family = AF_INET;
  98.     udpServer.sin_addr.s_addr = htonl(INADDR_ANY);
  99.     /* use the port passed as argument */
  100.     udpServer.sin_port = htons(atoi(argv[1]));
  101.  
  102.     /* bind to the socket */
  103.     returnStatus = bind(udpSocket, (struct sockaddr*)&udpServer, sizeof(udpServer));
  104.     if (returnStatus == 0) {
  105.        fprintf(stderr, "Bind completed!\n");
  106.     } else {
  107.         fprintf(stderr, "Could not bind to address!\n");
  108.         close(udpSocket); exit(1);
  109.     }
  110.  
  111.     /* Open user list and populate user array */
  112.     userFP = fopen("./userList.txt", "r");
  113.     if (userFP == NULL) {
  114.         fprintf(stderr, "Can't open the user list!\n");
  115.         exit(1);
  116.     }
  117.     for(int i = 0; fscanf(userFP, "%s %s", users[i].username, users[i].password) != EOF && i < numUsers; i++);
  118.     fclose(userFP);
  119.  
  120.     // client loop
  121.     while(1) {
  122.         addrlen = sizeof(udpClient);
  123.  
  124.         // auth loop
  125.         while(1) {
  126.             // receive username
  127.             printf("\nWaiting for user...\n");
  128.             returnStatus = recvfrom(udpSocket, username, 256, 0, (struct sockaddr*)&udpClient, &addrlen);
  129.             if (returnStatus == -1) {
  130.                 fprintf(stderr, "Client connection error.\n");
  131.                 continue;
  132.             }
  133.             printf("Received username: %s\n", username);
  134.  
  135.             // receive password
  136.             returnStatus = recvfrom(udpSocket, password, 256, 0, (struct sockaddr*)&udpClient, &addrlen);
  137.             if (returnStatus == -1) {
  138.                 fprintf(stderr, "Client connection error.\n");
  139.                 continue;
  140.             }
  141.             printf("Received password: %s\n", password);
  142.  
  143.             /* Check the name and port */
  144.             isAuthenticated = 0;
  145.             for(int i = 0; i < numUsers; i++) {
  146.                 if(!strcmp(username, users[i].username)) {
  147.                     if(!strcmp(password, users[i].password)) {
  148.                         isAuthenticated = 1;
  149.                     }
  150.                 }        
  151.             }
  152.  
  153.             // send authentication status to client
  154.             sprintf(buf, "%d", isAuthenticated);
  155.             returnStatus = sendto(udpSocket, buf, strlen(buf)+1, 0, (struct sockaddr*)&udpClient, sizeof(udpClient));
  156.  
  157.             if(isAuthenticated) {
  158.                 printf("Authenticated.\n\n");
  159.                 break;
  160.             }
  161.             printf("Authentication failed.\n\n");
  162.         }
  163.  
  164.         // file loop
  165.         while(1) {
  166.             printf("Waiting for filename...\n");
  167.             returnStatus = recvfrom(udpSocket, filename, 256, 0, (struct sockaddr*)&udpClient, &addrlen);
  168.             if (returnStatus == -1) {
  169.                 fprintf(stderr, "Client connection error.\n");
  170.                 continue;
  171.             }
  172.             printf("Received filename: %s\n", filename);
  173.             // check if file valid
  174.             clientFP = fopen(filename, "rb");
  175.             if(clientFP != NULL) {
  176.                 printf("Opened file: %s\n\n", filename);
  177.                 returnStatus = sendto(udpSocket, "1", 2, 0, (struct sockaddr*)&udpClient, sizeof(udpClient));
  178.                 break;
  179.             }
  180.             printf("Failed to open file: %s\n\n", filename);
  181.             returnStatus = sendto(udpSocket, "0", 2, 0, (struct sockaddr*)&udpClient, sizeof(udpClient));
  182.         }
  183.  
  184.         // send window size to client
  185.         returnStatus = sendto(udpSocket, argv[2], strlen(argv[2])+1, 0, (struct sockaddr*)&udpClient, sizeof(udpClient));
  186.  
  187.         // read file size
  188.         fseek(clientFP, 0L, SEEK_END);
  189.         fileSize = ftell(clientFP);
  190.         rewind(clientFP);
  191.  
  192.         // send number of packets
  193.         int totalNumPackets = fileSize / payloadSize + 1;
  194.         sprintf(buf, "%d", totalNumPackets);
  195.         returnStatus = sendto(udpSocket, buf, strlen(buf)+1, 0, (struct sockaddr*)&udpClient, sizeof(udpClient));
  196.  
  197.         // construct list to keep track of acknowledged packets
  198.         timerAckList = malloc(sizeof(time_t*) * totalNumPackets);
  199.         doNotSendList = malloc(sizeof(int) * totalNumPackets);
  200.         for(int i = 0; i < totalNumPackets; i++) { timerAckList[i] = (time_t*)malloc(sizeof(time_t)); }
  201.         for(int i = 0; i < totalNumPackets; i++) { (*timerAckList)[i] = 0; doNotSendList[i] = 0; }
  202.  
  203.         // read file into string
  204.         dataBuffer = (char*) malloc(sizeof(char) * (fileSize + 1) );
  205.         read_size = fread(dataBuffer, sizeof(char), fileSize, clientFP);
  206.         dataBuffer[fileSize] = '\0';
  207.  
  208.         if (fileSize != read_size) {
  209.            // error, free memory
  210.            free(dataBuffer);
  211.            dataBuffer = NULL;
  212.            continue;
  213.         }
  214.         fclose(clientFP);
  215.  
  216.         // create ack thread
  217.         printf("Creating ACK thread...\n");
  218.         if(pthread_create(&waitThread, NULL, waitForAck, param)) {
  219.             perror("ERROR creating thread.");
  220.         }
  221.         printf("ACK thread created.\n");
  222.  
  223.         // send packets loop
  224.         while(1) {
  225.  
  226.             // check if all packets are sent
  227.             int numSent = 0;
  228.             for(int i = 0; i < totalNumPackets; i++ ) {
  229.                 if(doNotSendList[i] == 1) numSent++;
  230.             }
  231.             if(numSent == totalNumPackets) {
  232.                 printf("File completely delivered!\n");
  233.                 numAcksReceived = numSent;
  234.                 break;
  235.             }
  236.  
  237.             // find first unsent packet
  238.             int startPacketNum = 0;
  239.             for(; startPacketNum < totalNumPackets; startPacketNum++) {
  240.                 if(doNotSendList[startPacketNum] == 1) continue;
  241.                 if((*timerAckList)[startPacketNum] == 0) break;
  242.             }
  243.  
  244.             // send a whole window
  245.             for(int windowIndex = 0; windowIndex < windowSize
  246.                 && startPacketNum + windowIndex < totalNumPackets; windowIndex++) {
  247.                 int currPacket = startPacketNum + windowIndex;
  248.                 if(doNotSendList[currPacket] == 1) { continue; }
  249.  
  250.                 // skip already ACKed packets
  251.                 time_t currTime = time(NULL);
  252.                 time_t sendTime = (*timerAckList)[currPacket];
  253.                 int secondsElapsed = currTime - sendTime;
  254.                 if(secondsElapsed < timeout) { continue; }
  255.  
  256.                 // construct packet
  257.                 int bufferIndex = currPacket*payloadSize;
  258.                 char header[headerSize] = "";
  259.                 sprintf(header, "%d", currPacket);
  260.                 char packet[packetSize] = "";
  261.                 strncpy(packet, header, headerSize);
  262.                 strncpy (&packet[headerSize], &dataBuffer[bufferIndex], payloadSize);
  263.                
  264.                 if (sendTime == 0) {
  265.                     printf("Transmitting SEQ%d\n", currPacket);
  266.                 } else {
  267.                     printf("Retransmitting SEQ%d\n", currPacket);
  268.                     numRetransmitted++;
  269.                 }
  270.                
  271.                 returnStatus = sendto(udpSocket, packet, sizeof(packet), 0, (struct sockaddr*)&udpClient, sizeof(udpClient));
  272.                 (*timerAckList)[currPacket] = time(NULL);
  273.             }          
  274.         }
  275.  
  276.         // convert to ip address
  277.         char ipAddress[INET_ADDRSTRLEN];
  278.         inet_ntop(AF_INET, &(udpClient.sin_addr), ipAddress, INET_ADDRSTRLEN);
  279.  
  280.         // calc date
  281.         time_t t = time(NULL);
  282.         struct tm *tm = localtime(&t);
  283.         char time[64];
  284.         strftime(time, sizeof(time), "%c", tm);
  285.  
  286.         // print out metrics
  287.         printf("\n=== METRICS ===\n");
  288.         // Receiver IP and Port Number
  289.         printf("Sent to IP %s, Port %d\n", ipAddress, ntohs(udpClient.sin_port));
  290.         // Name and Size of the file that was transferred
  291.         printf("Transferred file '%s' (%d bytes)\n", filename, fileSize);
  292.         // File Creation Date & Time
  293.         printf("File created: %s\n", time);
  294.         // Number of Data Packets Transmitted
  295.         printf("Sent %d data packets.\n", totalNumPackets);
  296.         // Number of Packets Re-transmitted
  297.         printf("Retransmitted %d packets.\n", numRetransmitted);
  298.         // Number of Acknowledgement Received
  299.         printf("Received %d ACKs.\n", numAcksReceived);
  300.         // Number of Negative Acknowledgement Received with Sequence Number
  301.         printf("Received %d NACKs.\n", numNacksReceived);
  302.  
  303.         // cleanup
  304.         free(dataBuffer);
  305.         for(int i = 0; i < totalNumPackets; i++) { free(timerAckList[i]); }
  306.         free(timerAckList);
  307.         free(doNotSendList);
  308.         pthread_cancel(waitThread);
  309.     }
  310.  
  311.     /* cleanup */
  312.     close(udpSocket);
  313.     return 0;
  314. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement