aboutsummaryrefslogtreecommitdiff
path: root/pa1_file_transfer/uftp_client.c
blob: 6e1adb6bb2153a89a45044128b5ec628ecd858ec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// File Transfer (Client)
// Jack Sangdahl
// 07 September 2024
#include <fcntl.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>

#define DATA_SIZE 1024

int main(int argc, char **argv) {
  if (argc != 3) {
    fprintf(stderr, "usage: %s <ip_addr> <port_num>\n", argv[0]);
    exit(EXIT_FAILURE);
  }
  char *hostname = argv[1];
  int port = atoi(argv[2]), sock;
  if (port > 65535 || port < 5000) {
    fprintf(stderr, "%s: port must be in range 5000-65535\n", argv[0]);
    exit(EXIT_FAILURE);
  }
  if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    fprintf(stderr, "%s: error opening socket\n", argv[0]);
    exit(EXIT_FAILURE);
  }
  struct hostent *server = gethostbyname(hostname);
  if (!server) {
    fprintf(stderr, "%s: error determining server\n", argv[0]);
    exit(EXIT_FAILURE);
  }
  struct sockaddr_in server_addr;
  memset(&server_addr, 0, sizeof(server_addr));
  server_addr.sin_family = AF_INET;
  server_addr.sin_port = htons(port);
  server_addr.sin_addr.s_addr = INADDR_ANY;
  memcpy((char *)&server_addr.sin_addr.s_addr, (char *)server->h_addr,
         server->h_length);
  socklen_t server_size = sizeof(server_addr);
  char data[DATA_SIZE], command[DATA_SIZE], filename[DATA_SIZE];
  while (1) {
    memset(data, 0, strlen(data));
    printf("usage: get [filename] | put [filename] | delete [filename] | ls | "
           "exit\n");
    fgets(data, DATA_SIZE, stdin);
    data[strcspn(data, "\n")] = 0;
    sscanf(data, "%s %s", command, filename);
    if (!strncmp(command, "get", 3)) {
      if (sendto(sock, data, strlen(data), 0, (struct sockaddr *)&server_addr,
                 server_size) < 0)
        fprintf(stderr, "%s: error sending data to server\n", argv[0]);
      int rec_data;
      if (recvfrom(sock, &rec_data, sizeof(rec_data), 0,
                   (struct sockaddr *)&server_addr, &server_size) < 0)
        fprintf(stderr, "%s: error receiving status from server\n", argv[0]);
      if (rec_data == -1) {
        fprintf(stderr, "error: file %s does not exist on server\n", filename);
        continue;
      }
      if (recvfrom(sock, data, sizeof(data), 0, (struct sockaddr *)&server_addr,
                   &server_size) < 0)
        fprintf(stderr, "%s: error receiving file size\n", argv[0]);
      int file_size = atoi(data);
      printf("receiving file %s/%d bytes from server...\n", filename,
             file_size);
      int f = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
      int bytes_transferred = 0;
      while (bytes_transferred < file_size) {
        memset(data, 0, sizeof(data));
        ssize_t received =
            recvfrom(sock, data, sizeof(data), 0,
                     (struct sockaddr *)&server_addr, &server_size);
        if (received < 0)
          fprintf(stderr, "%s: error receiving file data\n", argv[0]);
        write(f, data, received);
        bytes_transferred += received;
        printf("received %d/%d bytes\n", bytes_transferred, file_size);
      }
      close(f);
      printf("file transferred successfully.\n");
    } else if (!strncmp(command, "put", 3)) {
      printf("sending file %s to server...\n", filename);
      int f = open(filename, O_RDONLY);
      if (f < 0) {
        fprintf(stderr, "error: file %s does not exist in directory\n",
                filename);
        continue;
      }
      if (sendto(sock, data, strlen(data), 0, (struct sockaddr *)&server_addr,
                 server_size) < 0)
        fprintf(stderr, "%s: error sending data to server\n", argv[0]);
      off_t file_size = lseek(f, 0, SEEK_END);
      lseek(f, 0, SEEK_SET);
      char file_data[DATA_SIZE];
      sprintf(file_data, "%ld", (long)file_size);
      if (sendto(sock, file_data, DATA_SIZE, 0, (struct sockaddr *)&server_addr,
                 server_size) < 0)
        fprintf(stderr, "%s: error sending file size to server\n", argv[0]);
      memset(data, 0, sizeof(data));
      ssize_t bytes_read;
      while ((bytes_read = read(f, file_data, sizeof(file_data))) > 0) {
        if (sendto(sock, file_data, bytes_read, 0,
                   (struct sockaddr *)&server_addr, server_size) < 0) {
          fprintf(stderr, "%s: error sending data to server\n", argv[0]);
          break;
        }
        memset(file_data, 0, sizeof(file_data));
      }
      if (bytes_read < 0)
        fprintf(stderr, "error reading file %s\n", filename);
      else
        printf("file %s transferred successfully\n", filename);
      close(f);

    } else if (!strncmp(command, "delete", 6)) {
      if (sendto(sock, data, strlen(data), 0, (struct sockaddr *)&server_addr,
                 server_size) < 0)
        fprintf(stderr, "%s: error sending data to server\n", argv[0]);
      int rec_data;
      if (recvfrom(sock, &rec_data, sizeof(int), 0,
                   (struct sockaddr *)&server_addr, &server_size) < 0)
        fprintf(stderr, "%s: error receiving data from server\n", argv[0]);
      switch (rec_data) {
      case 0:
        printf("file %s deleted successfully\n", filename);
        break;
      case 1:
        printf("file %s does not exist on server\n", filename);
        break;
      case 2:
        printf("error deleting file %s on server\n", filename);
        break;
      }
    } else if (!strncmp(command, "ls", 2)) {
      if (sendto(sock, data, strlen(data), 0, (struct sockaddr *)&server_addr,
                 server_size) < 0)
        fprintf(stderr, "%s: error sending data to server\n", argv[0]);
      if (recvfrom(sock, data, sizeof(data), 0, (struct sockaddr *)&server_addr,
                   &server_size) < 0)
        fprintf(stderr, "%s: error receiving data from server\n", argv[0]);
      printf("%s\n", data);
    } else if (!strncmp(command, "exit", 4)) {
      if (sendto(sock, data, strlen(data), 0, (struct sockaddr *)&server_addr,
                 server_size) < 0)
        fprintf(stderr, "%s: error sending data to server\n", argv[0]);
      if (close(sock) < 0)
        fprintf(stderr, "%s: error closing socket\n", argv[0]);
      printf("%s: server connection closed\n", argv[0]);
      break;
    } else
      printf("invalid command!\n");
  }
  return EXIT_SUCCESS;
}