Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <errno.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netdb.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <sys/wait.h>
- #include <signal.h>
- #include <netdb.h>
- #include <pthread.h>
- #include <time.h>
- #define MAXBUF 1024
- #define numUsers 10
- #define packetSize 256
- #define payloadSize 248
- #define headerSize 8
- int udpSocket = 0;
- int returnStatus = 0;
- int isAuthenticated = 0;
- int windowSize = 1;
- int fileSize = 0;
- int read_size = 0;
- int timeout = 10;
- int numRetransmitted = 0;
- int numAcksReceived = 0;
- int numNacksReceived = 0;
- socklen_t addrlen;
- struct sockaddr_in udpServer;
- struct sockaddr_in udpClient;
- FILE *userFP;
- FILE *clientFP;
- char buf[MAXBUF];
- char username[256] = "";
- char password[256] = "";
- char filename[256] = "";
- char packetBuffer[256] = "";
- char *dataBuffer = NULL;
- time_t **timerAckList;
- int *doNotSendList;
- pthread_t waitThread;
- void* param;
- /* define a user */
- struct user {
- char username[256];
- char password[256];
- } users[numUsers];
- void *waitForAck(void* param) {
- while(1) {
- char threadBuf[256] = "";
- // printf("Listening....\n");
- int threadReturnStatus = recvfrom(udpSocket, threadBuf, 256, 0, (struct sockaddr*)&udpClient, &addrlen);
- if (threadReturnStatus == -1) {
- fprintf(stderr, "Client connection error in waitForAck thread.\n");
- continue;
- }
- // parse response
- int ackIndex = atoi(&threadBuf[3]);
- printf("Received ACK at index %d!!!\n", ackIndex);
- fflush(stdout);
- // set ACK
- // timerAckList[ackIndex] = NULL;
- doNotSendList[ackIndex] = 1;
- }
- return NULL;
- }
- int main(int argc, char* argv[]) {
- /* check for the right number of arguments */
- if (argc < 3) {
- fprintf(stderr, "Usage: %s <port> <window size>\n", argv[0]);
- exit(1);
- }
- windowSize = atoi(argv[2]);
- /* create a socket */
- udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
- if (udpSocket == -1) {
- fprintf(stderr, "Could not create a socket!\n");
- exit(1);
- } else {
- printf("Socket created.\n");
- }
- /* set up the server address and port */
- /* use INADDR_ANY to bind to all local addresses */
- udpServer.sin_family = AF_INET;
- udpServer.sin_addr.s_addr = htonl(INADDR_ANY);
- /* use the port passed as argument */
- udpServer.sin_port = htons(atoi(argv[1]));
- /* bind to the socket */
- returnStatus = bind(udpSocket, (struct sockaddr*)&udpServer, sizeof(udpServer));
- if (returnStatus == 0) {
- fprintf(stderr, "Bind completed!\n");
- } else {
- fprintf(stderr, "Could not bind to address!\n");
- close(udpSocket); exit(1);
- }
- /* Open user list and populate user array */
- userFP = fopen("./userList.txt", "r");
- if (userFP == NULL) {
- fprintf(stderr, "Can't open the user list!\n");
- exit(1);
- }
- for(int i = 0; fscanf(userFP, "%s %s", users[i].username, users[i].password) != EOF && i < numUsers; i++);
- fclose(userFP);
- // client loop
- while(1) {
- addrlen = sizeof(udpClient);
- // auth loop
- while(1) {
- // receive username
- printf("\nWaiting for user...\n");
- returnStatus = recvfrom(udpSocket, username, 256, 0, (struct sockaddr*)&udpClient, &addrlen);
- if (returnStatus == -1) {
- fprintf(stderr, "Client connection error.\n");
- continue;
- }
- printf("Received username: %s\n", username);
- // receive password
- returnStatus = recvfrom(udpSocket, password, 256, 0, (struct sockaddr*)&udpClient, &addrlen);
- if (returnStatus == -1) {
- fprintf(stderr, "Client connection error.\n");
- continue;
- }
- printf("Received password: %s\n", password);
- /* Check the name and port */
- isAuthenticated = 0;
- for(int i = 0; i < numUsers; i++) {
- if(!strcmp(username, users[i].username)) {
- if(!strcmp(password, users[i].password)) {
- isAuthenticated = 1;
- }
- }
- }
- // send authentication status to client
- sprintf(buf, "%d", isAuthenticated);
- returnStatus = sendto(udpSocket, buf, strlen(buf)+1, 0, (struct sockaddr*)&udpClient, sizeof(udpClient));
- if(isAuthenticated) {
- printf("Authenticated.\n\n");
- break;
- }
- printf("Authentication failed.\n\n");
- }
- // file loop
- while(1) {
- printf("Waiting for filename...\n");
- returnStatus = recvfrom(udpSocket, filename, 256, 0, (struct sockaddr*)&udpClient, &addrlen);
- if (returnStatus == -1) {
- fprintf(stderr, "Client connection error.\n");
- continue;
- }
- printf("Received filename: %s\n", filename);
- // check if file valid
- clientFP = fopen(filename, "rb");
- if(clientFP != NULL) {
- printf("Opened file: %s\n\n", filename);
- returnStatus = sendto(udpSocket, "1", 2, 0, (struct sockaddr*)&udpClient, sizeof(udpClient));
- break;
- }
- printf("Failed to open file: %s\n\n", filename);
- returnStatus = sendto(udpSocket, "0", 2, 0, (struct sockaddr*)&udpClient, sizeof(udpClient));
- }
- // send window size to client
- returnStatus = sendto(udpSocket, argv[2], strlen(argv[2])+1, 0, (struct sockaddr*)&udpClient, sizeof(udpClient));
- // read file size
- fseek(clientFP, 0L, SEEK_END);
- fileSize = ftell(clientFP);
- rewind(clientFP);
- // send number of packets
- int totalNumPackets = fileSize / payloadSize + 1;
- sprintf(buf, "%d", totalNumPackets);
- returnStatus = sendto(udpSocket, buf, strlen(buf)+1, 0, (struct sockaddr*)&udpClient, sizeof(udpClient));
- // construct list to keep track of acknowledged packets
- timerAckList = malloc(sizeof(time_t*) * totalNumPackets);
- doNotSendList = malloc(sizeof(int) * totalNumPackets);
- for(int i = 0; i < totalNumPackets; i++) { timerAckList[i] = (time_t*)malloc(sizeof(time_t)); }
- for(int i = 0; i < totalNumPackets; i++) { (*timerAckList)[i] = 0; doNotSendList[i] = 0; }
- // read file into string
- dataBuffer = (char*) malloc(sizeof(char) * (fileSize + 1) );
- read_size = fread(dataBuffer, sizeof(char), fileSize, clientFP);
- dataBuffer[fileSize] = '\0';
- if (fileSize != read_size) {
- // error, free memory
- free(dataBuffer);
- dataBuffer = NULL;
- continue;
- }
- fclose(clientFP);
- // create ack thread
- printf("Creating ACK thread...\n");
- if(pthread_create(&waitThread, NULL, waitForAck, param)) {
- perror("ERROR creating thread.");
- }
- printf("ACK thread created.\n");
- // send packets loop
- while(1) {
- // check if all packets are sent
- int numSent = 0;
- for(int i = 0; i < totalNumPackets; i++ ) {
- if(doNotSendList[i] == 1) numSent++;
- }
- if(numSent == totalNumPackets) {
- printf("File completely delivered!\n");
- numAcksReceived = numSent;
- break;
- }
- // find first unsent packet
- int startPacketNum = 0;
- for(; startPacketNum < totalNumPackets; startPacketNum++) {
- if(doNotSendList[startPacketNum] == 1) continue;
- if((*timerAckList)[startPacketNum] == 0) break;
- }
- // send a whole window
- for(int windowIndex = 0; windowIndex < windowSize
- && startPacketNum + windowIndex < totalNumPackets; windowIndex++) {
- int currPacket = startPacketNum + windowIndex;
- if(doNotSendList[currPacket] == 1) { continue; }
- // skip already ACKed packets
- time_t currTime = time(NULL);
- time_t sendTime = (*timerAckList)[currPacket];
- int secondsElapsed = currTime - sendTime;
- if(secondsElapsed < timeout) { continue; }
- // construct packet
- int bufferIndex = currPacket*payloadSize;
- char header[headerSize] = "";
- sprintf(header, "%d", currPacket);
- char packet[packetSize] = "";
- strncpy(packet, header, headerSize);
- strncpy (&packet[headerSize], &dataBuffer[bufferIndex], payloadSize);
- if (sendTime == 0) {
- printf("Transmitting SEQ%d\n", currPacket);
- } else {
- printf("Retransmitting SEQ%d\n", currPacket);
- numRetransmitted++;
- }
- returnStatus = sendto(udpSocket, packet, sizeof(packet), 0, (struct sockaddr*)&udpClient, sizeof(udpClient));
- (*timerAckList)[currPacket] = time(NULL);
- }
- }
- // convert to ip address
- char ipAddress[INET_ADDRSTRLEN];
- inet_ntop(AF_INET, &(udpClient.sin_addr), ipAddress, INET_ADDRSTRLEN);
- // calc date
- time_t t = time(NULL);
- struct tm *tm = localtime(&t);
- char time[64];
- strftime(time, sizeof(time), "%c", tm);
- // print out metrics
- printf("\n=== METRICS ===\n");
- // Receiver IP and Port Number
- printf("Sent to IP %s, Port %d\n", ipAddress, ntohs(udpClient.sin_port));
- // Name and Size of the file that was transferred
- printf("Transferred file '%s' (%d bytes)\n", filename, fileSize);
- // File Creation Date & Time
- printf("File created: %s\n", time);
- // Number of Data Packets Transmitted
- printf("Sent %d data packets.\n", totalNumPackets);
- // Number of Packets Re-transmitted
- printf("Retransmitted %d packets.\n", numRetransmitted);
- // Number of Acknowledgement Received
- printf("Received %d ACKs.\n", numAcksReceived);
- // Number of Negative Acknowledgement Received with Sequence Number
- printf("Received %d NACKs.\n", numNacksReceived);
- // cleanup
- free(dataBuffer);
- for(int i = 0; i < totalNumPackets; i++) { free(timerAckList[i]); }
- free(timerAckList);
- free(doNotSendList);
- pthread_cancel(waitThread);
- }
- /* cleanup */
- close(udpSocket);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement