├── Command line ├── Makefile ├── ftp_client.c ├── get_content.h ├── header.h ├── list_client.h ├── list_content.h ├── passive_connect.h ├── put_content.h ├── put_unique.h └── thread_get.h ├── GUI ├── Makefile ├── Screenshots │ ├── myftp.png │ └── myftp1.png ├── back1.png ├── get_content.h ├── gtk_final.c ├── header.h ├── list_client.h ├── list_content.h ├── list_content_view.h ├── logo.png ├── passive_connect.h ├── print_buff.h ├── print_buff1.h ├── put_content.h ├── put_unique.h └── thread_get.h └── README.md /Command line/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | FLG=-c -Wall 3 | 4 | all: myftp 5 | 6 | myftp: ftp_client.o 7 | @$(CC) ftp_client.o -o myftp -lpthread 8 | 9 | ftp_client.o: ftp_client.c 10 | @$(CC) $(FLG) ftp_client.c -lpthread 11 | 12 | clean: 13 | @rm *.o 14 | -------------------------------------------------------------------------------- /Command line/ftp_client.c: -------------------------------------------------------------------------------- 1 | #include"header.h" 2 | #include"list_client.h" 3 | #include"passive_connect.h" 4 | #include"list_content.h" 5 | #include"thread_get.h" 6 | #include"put_content.h" 7 | #include"put_unique.h" 8 | #include"get_content.h" 9 | 10 | /*Get home directory of user executing program */ 11 | char *find_home_dir(char *file) 12 | { 13 | struct passwd *pw; 14 | char *sudo_uid = getenv("SUDO_UID"); 15 | pw = getpwuid(atoi(sudo_uid)); 16 | 17 | return pw->pw_dir; 18 | 19 | } 20 | 21 | /*Validating IP Address*/ 22 | int validate_ip(char *ip) 23 | { 24 | int value_1 = MIN_VALUE; 25 | int value_2 = MIN_VALUE; 26 | int value_3 = MIN_VALUE; 27 | int value_4 = MIN_VALUE; 28 | int count = INITIALISE; 29 | int i = INITIALISE; 30 | 31 | while(ip[i] != '\0') 32 | { 33 | if(ip[i] == '.') 34 | count++; 35 | i++; 36 | } 37 | 38 | if(count != 3 ) 39 | return -1; 40 | else 41 | { 42 | sscanf(ip,"%d.%d.%d.%d",&value_1,&value_2,&value_3,&value_4); 43 | 44 | if(value_1 < MIN_IP || value_2 < MIN_IP || value_3 < MIN_IP || value_4 < MIN_IP || value_1 > MAX_IP || value_2 > MAX_IP || value_3 > MAX_IP || value_4 > MAX_IP)/* IP Addresses from 0.0.0.0 to 255.255.255.255*/ 45 | return -1; 46 | else 47 | return 1; 48 | 49 | } 50 | 51 | } 52 | 53 | int main(int argc, char *argv[]) 54 | { 55 | int sockfd;/* to create socket */ 56 | int no_of_bytes;/* number of bytes sent or received from server */ 57 | 58 | /*Temporary Variables*/ 59 | int connect_value; 60 | int ip_valid; 61 | int temp = MIN_VALUE; 62 | int count; 63 | int dir_check; 64 | 65 | clock_t start,end; 66 | double cpu_time; 67 | 68 | struct sockaddr_in serverAddress;/* client will connect on this */ 69 | 70 | char ch[MAXSZ]; 71 | char message_from_server[MAXSZ];/* message from server*/ 72 | char user_input[MAXSZ];/* input from user */ 73 | char message_to_server[MAXSZ];/* message to server */ 74 | char dir[MAXSZ];/* directory name */ 75 | char username[MAXSZ];/* username entered by the user */ 76 | char working_dir[MAXSZ]; 77 | char old_name[MAXSZ]; 78 | char new_name[MAXSZ]; 79 | 80 | char *home_dir; 81 | char *password = malloc(MAXSZ);/* password enterd by user */ 82 | 83 | if(argc != 2) /* `./executable ip-adddress` */ 84 | { 85 | printf("Error: argument should be ip-address of server\n"); 86 | exit(1); 87 | } 88 | 89 | ip_valid = validate_ip(argv[1]);/* Validate ip-address entered by user */ 90 | 91 | if(ip_valid == MIN_VALUE)/* Invalid ipaddress */ 92 | { 93 | printf("Error: Invalid ip-address\n"); 94 | exit(1); 95 | } 96 | 97 | home_dir = find_home_dir(argv[0]);/* Home directory of user executing the program */ 98 | 99 | sockfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);/* Create socket */ 100 | 101 | if(sockfd == -1)/* Error in socket creation */ 102 | { 103 | perror("Error"); 104 | exit(1); 105 | } 106 | 107 | bzero(&serverAddress,sizeof(serverAddress));/* Initialise structure */ 108 | 109 | serverAddress.sin_family = AF_INET; 110 | serverAddress.sin_addr.s_addr = inet_addr(argv[1]); 111 | serverAddress.sin_port = htons(PORT); 112 | 113 | /* Connect to server */ 114 | connect_value = connect(sockfd,(struct sockaddr *)&serverAddress,sizeof(serverAddress)); 115 | if(connect_value == -1)/* Connection Error */ 116 | { 117 | perror("Error"); 118 | exit(1); 119 | } 120 | 121 | printf("Connected to %s.\n",argv[1]); 122 | 123 | /* Receive message from server "Server will send 220" */ 124 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0 ) 125 | { 126 | message_from_server[no_of_bytes] = '\0'; 127 | printf("%s\n",message_from_server); 128 | fflush(stdout); 129 | 130 | if(strstr(message_from_server,"220 ") > 0 || strstr(message_from_server,"421 ") > 0) 131 | break; 132 | } 133 | 134 | if(strstr(message_from_server,"421 ") > 0) 135 | exit(1); 136 | 137 | printf("Name (%s): ",argv[1]); 138 | scanf("%s",username);/* Enter name of user on server */ 139 | 140 | sprintf(user,"USER %s\r\n",username); 141 | 142 | send(sockfd,user,strlen(user),0);/* Send username to server */ 143 | 144 | 145 | /* 146 | Receive message from server after sending user name. 147 | Message with code 331 asks you to enter password corresponding to user. 148 | Message with code 230 means no password is required for the entered username(LOGIN successful). 149 | */ 150 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 151 | { 152 | message_from_server[no_of_bytes] = '\0'; 153 | if(strncmp(message_from_server,"331",3) == 0) 154 | { 155 | temp = 1; 156 | } 157 | 158 | if(strncmp(message_from_server,"230",3) == 0) 159 | { 160 | temp = 2; 161 | } 162 | 163 | if(strncmp(message_from_server,"530",3) == 0) 164 | { 165 | temp = 0; 166 | } 167 | printf("%s\n",message_from_server); 168 | if(strstr(message_from_server,"230 ") > 0 || strstr(message_from_server,"500 ") > 0 || strstr(message_from_server,"501 ") > 0 || strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"332 ") > 0 || strstr(message_from_server,"530 ")|| strstr(message_from_server,"331 ") > 0) 169 | break; 170 | fflush(stdout); 171 | } 172 | 173 | if(temp == 1) 174 | { 175 | password = getpass("Password: ");/* Enter password */ 176 | sprintf(pass,"PASS %s\r\n",password); 177 | 178 | send(sockfd,pass,strlen(pass),0);/* Send password to server */ 179 | 180 | /* Receive message from server */ 181 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 182 | { 183 | message_from_server[no_of_bytes] = '\0'; 184 | 185 | if(strncmp(message_from_server,"230",3) == 0) 186 | { 187 | temp = 2; 188 | } 189 | 190 | if(strncmp(message_from_server,"530",3) == 0) 191 | { 192 | temp = 0; 193 | } 194 | printf("%s\n",message_from_server); 195 | 196 | if(strstr(message_from_server,"230 ") > 0 || strstr(message_from_server,"500 ") > 0 || strstr(message_from_server,"501 ") > 0 || strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"332 ") > 0 || strstr(message_from_server,"530 ")|| strstr(message_from_server,"503 ") > 0 || strstr(message_from_server,"202 ") > 0) 197 | break; 198 | 199 | fflush(stdout); 200 | 201 | } 202 | } 203 | 204 | if(temp == 0) 205 | { 206 | exit(1); 207 | } 208 | 209 | 210 | /* System type(Server) */ 211 | sprintf(message_to_server,"SYST\r\n"); 212 | send(sockfd,message_to_server,strlen(message_to_server),0); 213 | 214 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 215 | { 216 | message_from_server[no_of_bytes] = '\0'; 217 | printf("%s\n",message_from_server); 218 | if(strstr(message_from_server,"215 ") > 0 || strstr(message_from_server,"500 ") > 0 || strstr(message_from_server,"501 ") > 0 || strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"502 ") > 0) 219 | break; 220 | 221 | } 222 | 223 | 224 | /* Infinite Loop for user operation */ 225 | while(1) 226 | { 227 | temp = 0; 228 | 229 | printf("ftp> "); 230 | fflush(stdout); 231 | 232 | /* Initialise strings */ 233 | bzero(user_input,MAXSZ); 234 | bzero(message_to_server,MAXSZ); 235 | bzero(message_from_server,MAXSZ); 236 | bzero(working_dir,MAXSZ); 237 | bzero(old_name,MAXSZ); 238 | bzero(new_name,MAXSZ); 239 | 240 | /* Read user input */ 241 | no_of_bytes = read(STDIN_FILENO,user_input,MAXSZ); 242 | user_input[no_of_bytes] = '\0'; 243 | 244 | /* Remove trailing return and newline characters */ 245 | if(user_input[no_of_bytes - 1] == '\n') 246 | user_input[no_of_bytes - 1] = '\0'; 247 | if(user_input[no_of_bytes - 1] == '\r') 248 | user_input[no_of_bytes - 1] = '\0'; 249 | 250 | /* User wants to exit */ 251 | if(strcmp(user_input,"exit") == 0 || strcmp(user_input,"quit") == 0 || strcmp(user_input,"bye") == 0) 252 | { 253 | sprintf(message_to_server,"QUIT\r\n"); 254 | 255 | /* Send message to server */ 256 | send(sockfd,message_to_server,strlen(message_to_server),0); 257 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 258 | { 259 | message_from_server[no_of_bytes] = '\0'; 260 | printf("%s\n",message_from_server); 261 | if(strstr(message_from_server,"221 ") > 0 || strstr(message_from_server,"500 ") > 0) 262 | break; 263 | } 264 | break; 265 | } 266 | 267 | /* Change directory on client side */ 268 | if(strncmp(user_input,"!cd ",4) == 0 || strcmp(user_input,"!cd") == 0) 269 | { 270 | if(chdir(user_input + 4) == 0) 271 | { 272 | printf("Directory successfully changed\n\n"); 273 | } 274 | else 275 | { 276 | perror("Error"); 277 | } 278 | } 279 | 280 | /* Current working directory on client side */ 281 | if(strncmp(user_input,"!pwd ",5) == 0 || strcmp(user_input,"!pwd") == 0) 282 | { 283 | getcwd(working_dir,MAXSZ); 284 | printf("%s\n\n",working_dir); 285 | } 286 | 287 | /* List files with details in current working directory on client side */ 288 | if(strncmp(user_input,"!ls -l ",7) == 0 || strcmp(user_input,"!ls -l") == 0) 289 | { 290 | getcwd(working_dir,MAXSZ); 291 | ls_l_dir(working_dir); 292 | continue; 293 | } 294 | 295 | /* List files in current working directory on client side */ 296 | if(strncmp(user_input,"!ls ",4) == 0 || strcmp(user_input,"!ls") == 0) 297 | { 298 | getcwd(working_dir,MAXSZ); 299 | ls_dir(working_dir); 300 | } 301 | 302 | /* Create directory on client side */ 303 | if(strncmp(user_input,"!mkdir ",7) == 0) 304 | { 305 | dir_check = mkdir(user_input + 7,0755); 306 | if(dir_check == -1) 307 | perror("Error"); 308 | else 309 | printf("Directory successfully created\n"); 310 | printf("\n"); 311 | } 312 | 313 | /* Remove directory on client side */ 314 | if(strncmp(user_input,"!rmdir ",7) == 0) 315 | { 316 | dir_check = rmdir(user_input + 7); 317 | if(dir_check == -1) 318 | perror("Error"); 319 | else 320 | printf("Directory successfully removed\n"); 321 | printf("\n"); 322 | } 323 | 324 | /* Change directory on server side */ 325 | if(strncmp(user_input,"cd ",3) == 0) 326 | { 327 | sprintf(dir,"CWD %s\r\n",user_input + 3); 328 | send(sockfd,dir,strlen(dir),0); 329 | 330 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 331 | { 332 | message_from_server[no_of_bytes] = '\0'; 333 | printf("%s\n",message_from_server); 334 | fflush(stdout); 335 | 336 | if(strstr(message_from_server,"530 ") > 0 || strstr(message_from_server,"250 ") > 0 || strstr(message_from_server,"500 ") > 0 || strstr(message_from_server,"501 ") > 0 || strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"502 ") > 0 || strstr(message_from_server,"550 ") > 0) 337 | break; 338 | } 339 | } 340 | 341 | //* List files on server side */ 342 | if(strncmp(user_input,"ls ",3)== 0 || strcmp(user_input,"ls")== 0) 343 | { 344 | list_content(argv[1],user_input,sockfd); 345 | } 346 | 347 | /* Current working directory on server side */ 348 | if(strcmp(user_input,"pwd")== 0) 349 | { 350 | sprintf(message_to_server,"PWD\r\n"); 351 | send(sockfd,message_to_server,strlen(message_to_server),0); 352 | 353 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 354 | { 355 | message_from_server[no_of_bytes] = '\0'; 356 | printf("%s\n",message_from_server); 357 | fflush(stdout); 358 | 359 | if(strstr(message_from_server,"257 ") > 0 || strstr(message_from_server,"500 ") > 0 || strstr(message_from_server,"501 ") > 0 || strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"502 ") > 0 || strstr(message_from_server,"550 ") > 0) 360 | break; 361 | } 362 | } 363 | 364 | /* Download file from server */ 365 | if(strncmp(user_input,"get ",4) == 0) 366 | { 367 | start = clock(); 368 | get_content(argv[1],user_input,sockfd,home_dir); 369 | end = clock(); 370 | cpu_time = ((double)(end - start))/CLOCKS_PER_SEC; 371 | printf("Time taken %lf\n\n",cpu_time); 372 | } 373 | 374 | /* Upload file to server */ 375 | if(strncmp(user_input,"put ",4)== 0) 376 | { 377 | put_content(argv[1],user_input,sockfd); 378 | } 379 | 380 | /* Upload file uniquely to server */ 381 | if(strncmp(user_input,"uniqput ",8)== 0) 382 | { 383 | put_unique(argv[1],user_input,sockfd); 384 | } 385 | 386 | /* Rename file on server */ 387 | if(strncmp(user_input,"rename ",7) == 0) 388 | { 389 | 390 | /* parse user input to get old file name and new file name */ 391 | count = sscanf(user_input,"%s %s %s",message_to_server,old_name,new_name); 392 | 393 | if(count != 3) 394 | { 395 | printf("Error: rename expects two arguments\n\n"); 396 | continue; 397 | } 398 | 399 | sprintf(message_to_server,"RNFR %s\r\n",old_name); 400 | 401 | send(sockfd,message_to_server,strlen(message_to_server),0); 402 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0 ) 403 | { 404 | message_from_server[no_of_bytes] = '\0'; 405 | 406 | if(strncmp(message_from_server,"550",3) == 0)/* RNFR fails*/ 407 | { 408 | temp = 1; 409 | } 410 | printf("%s\n",message_from_server); 411 | 412 | fflush(stdout); 413 | 414 | if(strstr(message_from_server,"350 ") > 0 || strstr(message_from_server,"450 ") > 0 || strstr(message_from_server,"530 ") > 0 || strstr(message_from_server,"500 ") > 0|| strstr(message_from_server,"501 ") > 0 || strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"502 ") > 0 || strstr(message_from_server,"550 ") > 0) 415 | break; 416 | } 417 | 418 | if(temp == 1) 419 | continue; 420 | 421 | sprintf(message_to_server,"RNTO %s\r\n",new_name); 422 | 423 | send(sockfd,message_to_server,strlen(message_to_server),0); 424 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0 ) 425 | { 426 | message_from_server[no_of_bytes] = '\0'; 427 | if(strncmp(message_from_server,"550",3) == 0)/* RNTO fails*/ 428 | { 429 | printf("Error: Renaming file failed.\n\n"); 430 | } 431 | else 432 | printf("%s\n",message_from_server); 433 | 434 | fflush(stdout); 435 | 436 | if(strstr(message_from_server,"553 ") > 0 ||strstr(message_from_server,"250 ") > 0 || strstr(message_from_server,"532 ") > 0 || strstr(message_from_server,"530 ") > 0 || strstr(message_from_server,"500 ") > 0|| strstr(message_from_server,"501 ") > 0 || strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"502 ") > 0 || strstr(message_from_server,"503 ") > 0) 437 | break; 438 | 439 | } 440 | 441 | 442 | } 443 | 444 | /* Creating diectory on server */ 445 | if(strncmp(user_input,"mkdir ",6) == 0) 446 | { 447 | sprintf(message_to_server,"MKD %s\r\n",user_input + 6); 448 | send(sockfd,message_to_server,strlen(message_to_server),0); 449 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0 ) 450 | { 451 | message_from_server[no_of_bytes] = '\0'; 452 | if(strncmp(message_from_server,"550",3) == 0)/* MKD fails*/ 453 | { 454 | printf("Error: Creating directory failed.\n\n"); 455 | } 456 | else 457 | printf("%s\n",message_from_server); 458 | 459 | fflush(stdout); 460 | 461 | if(strstr(message_from_server,"257 ") > 0 || strstr(message_from_server,"530 ") > 0 || strstr(message_from_server,"500 ") > 0|| strstr(message_from_server,"501 ") > 0 || strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"502 ") > 0 || strstr(message_from_server,"550 ") > 0) 462 | break; 463 | 464 | } 465 | } 466 | 467 | /* Removing directory on server */ 468 | if(strncmp(user_input,"rmdir ",6) == 0) 469 | { 470 | sprintf(message_to_server,"RMD %s\r\n",user_input + 6); 471 | send(sockfd,message_to_server,strlen(message_to_server),0); 472 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0 ) 473 | { 474 | message_from_server[no_of_bytes] = '\0'; 475 | if(strncmp(message_from_server,"550",3) == 0)/* RMD fails*/ 476 | { 477 | printf("Error: Removing directory failed.\n\n"); 478 | } 479 | else 480 | printf("%s\n",message_from_server); 481 | 482 | fflush(stdout); 483 | 484 | if(strstr(message_from_server,"250 ") > 0 || strstr(message_from_server,"530 ") > 0 || strstr(message_from_server,"500 ") > 0|| strstr(message_from_server,"501 ") > 0 || strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"502 ") > 0 || strstr(message_from_server,"550 ") > 0) 485 | break; 486 | } 487 | } 488 | 489 | /* Delete file on server */ 490 | if(strncmp(user_input,"rm ",3) == 0) 491 | { 492 | printf("Do you really want to remove this file? yes/no \n"); 493 | 494 | scanf("%s",ch); 495 | 496 | if(strcasecmp(ch,"yes") != 0) 497 | continue; 498 | 499 | sprintf(message_to_server,"DELE %s\r\n",user_input + 3); 500 | 501 | send(sockfd,message_to_server,strlen(message_to_server),0); 502 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0 ) 503 | { 504 | message_from_server[no_of_bytes] = '\0'; 505 | if(strncmp(message_from_server,"550",3) == 0)/* DEL fails*/ 506 | { 507 | printf("Error: Removing file failed.\n\n"); 508 | } 509 | else 510 | printf("%s\n",message_from_server); 511 | 512 | fflush(stdout); 513 | 514 | if(strstr(message_from_server,"250 ") > 0 || strstr(message_from_server,"450 ") > 0 || strstr(message_from_server,"530 ") > 0 || strstr(message_from_server,"500 ") > 0|| strstr(message_from_server,"501 ") > 0 || strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"502 ") > 0 || strstr(message_from_server,"550 ") > 0) 515 | break; 516 | 517 | } 518 | } 519 | 520 | 521 | } 522 | close(sockfd); 523 | return 0; 524 | } 525 | -------------------------------------------------------------------------------- /Command line/get_content.h: -------------------------------------------------------------------------------- 1 | /* 2 | Download files from server. 3 | */ 4 | 5 | void get_content(char *arg,char *user_input,int sockfd,char *home_dir) 6 | { 7 | /* Temporary variables*/ 8 | int no_of_bytes; 9 | int port; 10 | int newsockfd; 11 | int i; 12 | int j = 0; 13 | int count = 0; 14 | int size; 15 | int no_of_threads; 16 | int total; 17 | int partial_bytes; 18 | int filehandle; 19 | int fd; 20 | 21 | char message_from_server[MAXSZ]; 22 | char message_to_server[MAXSZ]; 23 | char file[MAXSZ];// File name 24 | char file_name[MAXSZ];// File name with instruction to server 25 | char file_home_dir[MAXSZ];// Location of file i.e. User's home directory(Complete path to file). 26 | char data[MAXSZ];// Data transfer 27 | char pwd[MAXSZ]; 28 | char size_file[MAXSZ];// size of file 29 | char temp_file[MAXSZ];//temporary files created on client side 30 | 31 | /* Initialise all the character arrays */ 32 | bzero(message_from_server,MAXSZ); 33 | bzero(message_to_server,MAXSZ); 34 | bzero(file_name,MAXSZ); 35 | bzero(file,MAXSZ); 36 | bzero(file_home_dir,MAXSZ); 37 | bzero(data,MAXSZ); 38 | bzero(pwd,MAXSZ); 39 | bzero(size_file,MAXSZ); 40 | bzero(temp_file,MAXSZ); 41 | 42 | /* Getting file size from server*/ 43 | sprintf(size_file,"SIZE %s\r\n",user_input + 4); 44 | send(sockfd,size_file,strlen(size_file),0); 45 | 46 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 47 | { 48 | message_from_server[no_of_bytes] = '\0'; 49 | if(strstr(message_from_server,"213 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"502 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"550 ") > 0) 50 | break; 51 | } 52 | 53 | size = atoi(message_from_server + 4);/* Convertin string to integer */ 54 | 55 | /* Getting current working dirctory */ 56 | send(sockfd,"PWD\r\n",5,0); 57 | 58 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 59 | { 60 | message_from_server[no_of_bytes] = '\0'; 61 | if(strstr(message_from_server,"257 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"502 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"550 ") > 0) 62 | break; 63 | } 64 | 65 | /* Exract current working directory name from the message */ 66 | for(i = 0; message_from_server[i]!='\0';i++) 67 | { 68 | if(message_from_server[i] == '\"' && count == 1) 69 | { 70 | break; 71 | } 72 | 73 | if(count == 1) 74 | { 75 | pwd[j++] = message_from_server[i]; 76 | } 77 | 78 | if(message_from_server[i] == '\"' && count == 0) 79 | { 80 | count = 1; 81 | } 82 | 83 | } 84 | pwd[j] = '\0'; 85 | 86 | 87 | /* Tell server to change to BINARY mode */ 88 | send(sockfd,"TYPE I\r\n",8,0); 89 | 90 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 91 | { 92 | message_from_server[no_of_bytes] = '\0'; 93 | printf("%s",message_from_server); 94 | fflush(stdout); 95 | if(strstr(message_from_server,"200 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"504 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 96 | break; 97 | } 98 | printf("\n"); 99 | 100 | if(strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"504 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 101 | return; 102 | 103 | /* Send request for PASSIVE connection */ 104 | send(sockfd,passive,strlen(passive),0); 105 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 106 | { 107 | message_from_server[no_of_bytes] = '\0'; 108 | printf("%s",message_from_server); 109 | fflush(stdout); 110 | if(strstr(message_from_server,"227 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"502 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 111 | break; 112 | } 113 | 114 | printf("\n"); 115 | if(strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"502 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 116 | return; 117 | 118 | /* Server accepts request and sends PORT variables */ 119 | if(strncmp(message_from_server,"227",3) == 0) 120 | { 121 | /* Generate a PORT number using PORT variables */ 122 | port = passive_port_number(message_from_server); 123 | 124 | /* Connect to server using another PORT for file transfers */ 125 | newsockfd = func_to_connect_passive(arg,port); 126 | // fcntl(newsockfd,F_SETFL,FNDELAY); 127 | 128 | sprintf(file,"%s",user_input + 4); 129 | 130 | /* Send file name */ 131 | sprintf(file_name,"RETR %s\r\n",user_input + 4); 132 | send(sockfd,file_name,strlen(file_name),0); 133 | 134 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 135 | { 136 | message_from_server[no_of_bytes] = '\0'; 137 | printf("%s",message_from_server); 138 | fflush(stdout); 139 | if(strstr(message_from_server,"425 ") > 0|| strstr(message_from_server,"125 ") > 0 ||strstr(message_from_server,"150 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"550 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 140 | break; 141 | } 142 | printf("\n"); 143 | 144 | /* Permission Denied */ 145 | if(strncmp(message_from_server,"550",3) == 0 || strncmp(message_from_server,"425",3) == 0) 146 | { 147 | close(newsockfd); 148 | return; 149 | } 150 | else 151 | { 152 | sprintf(file_home_dir,"%s/%s",home_dir,file); 153 | 154 | /* Create file on client system */ 155 | filehandle = open(file_home_dir,O_CREAT|O_WRONLY|O_TRUNC,0644); 156 | 157 | /* Decide total number of threads to be created */ 158 | if(size <= 5000) 159 | no_of_threads = 1; 160 | else if(size > 5000 && size < 100000) 161 | no_of_threads = 4; 162 | else 163 | no_of_threads = 10; 164 | 165 | if(no_of_threads > 1)// Multithreading 166 | { 167 | /* initilise structure for each thread */ 168 | struct userdetails user[no_of_threads]; 169 | pthread_t thre[no_of_threads]; 170 | pthread_attr_t attr; 171 | pthread_attr_init(&attr); 172 | pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE); 173 | 174 | 175 | for(i = 0;i < no_of_threads;i++)// Initialise structures 176 | { 177 | strcpy(user[i].arg,arg); 178 | strcpy(user[i].home_dir,home_dir); 179 | strcpy(user[i].user_input,user_input); 180 | strcpy(user[i].pwd,pwd); 181 | if(size % no_of_threads == 0) 182 | user[i].size = size/no_of_threads; 183 | else 184 | user[i].size = size/no_of_threads + 1; 185 | } 186 | 187 | for( i = 0;i < no_of_threads;i++)// Create threads 188 | { 189 | user[i].t_id = i; 190 | pthread_create(&thre[i],&attr,function,(void *)&user[i]); 191 | } 192 | 193 | printf("Downloading...\n\n"); 194 | fflush(stdout); 195 | 196 | pthread_attr_destroy(&attr); 197 | for(i = 0;i < no_of_threads;i++)// Wait for completion of all threads 198 | { 199 | pthread_join(thre[i],NULL); 200 | } 201 | 202 | close(newsockfd);// Close passive connection 203 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0)//Server might send an error message. We can ignore this. 204 | { 205 | message_from_server[no_of_bytes] = '\0'; 206 | if(strstr(message_from_server,"226 ") > 0 || strstr(message_from_server,"426 ") > 0) 207 | break; 208 | } 209 | 210 | printf("Combining data...\n\n"); 211 | fflush(stdout); 212 | 213 | for(i = 0; i < no_of_threads; i++)//Joining temporary files 214 | { 215 | sprintf(temp_file,"%s/%s%d",home_dir,user_input + 4,i); 216 | fd = open(temp_file,O_RDONLY); 217 | 218 | while((no_of_bytes = read(fd,data,MAXSZ)) > 0) 219 | { 220 | data[no_of_bytes] = '\0'; 221 | total = 0; 222 | while(total < no_of_bytes) 223 | { 224 | partial_bytes = write(filehandle,data + total,no_of_bytes - total); 225 | total += partial_bytes; 226 | } 227 | } 228 | close(fd); 229 | unlink(temp_file); 230 | } 231 | close(filehandle); 232 | printf("226 Transfer completed\n\n"); 233 | fflush(stdout); 234 | 235 | } 236 | else//if file size is small. No need of multithreading 237 | { 238 | 239 | while((no_of_bytes = recv(newsockfd,data,MAXSZ,0))>0)//get data on passive connection 240 | { 241 | total = 0; 242 | /* For partial write operations */ 243 | while(total < no_of_bytes) 244 | { 245 | partial_bytes = write(filehandle,data + total,no_of_bytes - total); 246 | total += partial_bytes; 247 | } 248 | } 249 | 250 | /* Close PASSIVE socket and file */ 251 | close(newsockfd); 252 | close(filehandle); 253 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0))>0) 254 | { 255 | message_from_server[no_of_bytes] = '\0'; 256 | printf("%s",message_from_server); 257 | fflush(stdout); 258 | if(strstr(message_from_server,"226 ") > 0 || strstr(message_from_server,"426 ") > 0) 259 | break; 260 | } 261 | printf("\n"); 262 | } 263 | } 264 | } 265 | } 266 | 267 | -------------------------------------------------------------------------------- /Command line/header.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include//socket 3 | #include//socket 4 | #include//sizeof 5 | #include 6 | #include 7 | #include 8 | #include//isdigit() 9 | #include//open() 10 | #include 11 | #include//stat() 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define PORT 21 18 | #define MAXSZ 4096 19 | 20 | #define MIN_VALUE -1 21 | #define INITIALISE 0 22 | #define MIN_IP 0 23 | #define MAX_IP 255 24 | 25 | struct userdetails 26 | { 27 | char arg[MAXSZ]; 28 | char user_input[MAXSZ]; 29 | char home_dir[MAXSZ]; 30 | char pwd[MAXSZ]; 31 | int t_id; 32 | int size; 33 | }; 34 | 35 | char user[MAXSZ];/* user details sent to server */ 36 | char pass[MAXSZ];/* password details sent to server */ 37 | char passive[]="PASV\r\n"; 38 | -------------------------------------------------------------------------------- /Command line/list_client.h: -------------------------------------------------------------------------------- 1 | /* 2 | List files in current working directory on client side. 3 | */ 4 | 5 | /* Return result of character comparison(Ignoring LETTER CASE)*/ 6 | int mycompare(const void *a, const void *b) 7 | { 8 | return strcasecmp(*(const char **)a,*(const char **)b); 9 | } 10 | 11 | 12 | /* `ls` comand in linux. List files in current working directory without details.*/ 13 | void ls_dir(char *dir_name) 14 | { 15 | DIR *fd; 16 | 17 | char *arg[MAXSZ]; 18 | 19 | int i = INITIALISE; 20 | int n; 21 | 22 | struct dirent *entry; 23 | fd = opendir(dir_name);/* Open directory */ 24 | if(fd == NULL) 25 | { 26 | perror("Error"); 27 | return; 28 | } 29 | 30 | while((entry = readdir(fd))!=NULL)/* Ignore hidden files */ 31 | { 32 | if(entry->d_name[0] != '.' && strcmp(entry->d_name,".") != 0 && strcmp(entry->d_name,"..") != 0) 33 | { 34 | *(arg + i) = entry->d_name; 35 | i++; 36 | } 37 | } 38 | 39 | n = i; 40 | 41 | qsort(arg,n,sizeof(const char *),mycompare);/* Sort file names in alphabetical order ignoring LETTER CASE*/ 42 | 43 | i = 0; 44 | while(i < n) 45 | { 46 | printf("%s\n",*(arg + i)); 47 | i++; 48 | } 49 | 50 | printf("\n"); 51 | closedir(fd); 52 | } 53 | 54 | void ls_l_dir(char *dir_name) 55 | { 56 | char time_buff[MAXSZ]; 57 | char *arg[MAXSZ]; 58 | 59 | int i = INITIALISE; 60 | int n; 61 | int val = INITIALISE; 62 | int temp; 63 | 64 | struct group *gp;/* structure contating group details */ 65 | struct passwd *pw;/* structure containing passwd file */ 66 | struct tm *info; 67 | struct stat buff; 68 | struct dirent *entry; 69 | DIR *fd; 70 | fd = opendir(dir_name);/* Open directory */ 71 | if(fd == NULL) 72 | { 73 | perror("Error"); 74 | return; 75 | } 76 | 77 | while((entry = readdir(fd))!= NULL)/* Read directory */ 78 | { 79 | 80 | /* Call kiya tha */ 81 | if(strcmp(entry->d_name,".") != 0 && strcmp(entry->d_name,"..") != 0 && entry->d_name[0]!= '.') 82 | { 83 | *(arg + i) = entry->d_name; 84 | i++; 85 | } 86 | 87 | } 88 | 89 | n = i; 90 | qsort(arg,n,sizeof(const char *),mycompare); 91 | 92 | i = 0; 93 | while(i < n) 94 | { 95 | lstat(*(arg + i),&buff); 96 | gp = getgrgid(buff.st_gid); 97 | pw = getpwuid(buff.st_uid); 98 | info = localtime(&(buff.st_mtime)); 99 | strftime(time_buff,sizeof(time_buff),"%b %d %H:%M",info); 100 | 101 | if(buff.st_size % 1024 == 0) 102 | { 103 | temp = (int)buff.st_size / 1024; 104 | val += temp ; 105 | } 106 | else 107 | { 108 | temp = ((int)buff.st_size / 1024); 109 | val += (temp + (4 - (temp % 4))); 110 | } 111 | 112 | /* Selecting file type */ 113 | switch(buff.st_mode & S_IFMT) 114 | { 115 | case S_IFCHR: 116 | printf("c"); 117 | break; 118 | case S_IFBLK: 119 | printf("b"); 120 | break; 121 | case S_IFDIR: 122 | printf("d"); 123 | break; 124 | case S_IFLNK: 125 | printf("l"); 126 | break; 127 | case S_IFIFO: 128 | printf("p"); 129 | break; 130 | case S_IFSOCK: 131 | printf("s"); 132 | break; 133 | default: 134 | printf("-"); 135 | break; 136 | } 137 | 138 | 139 | /* File permissions */ 140 | if(buff.st_mode & S_IRUSR) 141 | printf("r"); 142 | else 143 | printf("-"); 144 | 145 | if(buff.st_mode & S_IWUSR) 146 | printf("w"); 147 | else 148 | printf("-"); 149 | 150 | if(buff.st_mode & S_IXUSR) 151 | printf("x"); 152 | else 153 | printf("-"); 154 | 155 | if(buff.st_mode & S_IRGRP) 156 | printf("r"); 157 | else 158 | printf("-"); 159 | 160 | if(buff.st_mode & S_IWGRP) 161 | printf("w"); 162 | else 163 | printf("-"); 164 | 165 | if(buff.st_mode & S_IXGRP) 166 | printf("x"); 167 | else 168 | printf("-"); 169 | 170 | if(buff.st_mode & S_IROTH) 171 | printf("r"); 172 | else 173 | printf("-"); 174 | 175 | if(buff.st_mode & S_IWOTH) 176 | printf("w"); 177 | else 178 | printf("-"); 179 | 180 | if(buff.st_mode & S_IXOTH) 181 | printf("x"); 182 | else 183 | printf("-"); 184 | 185 | 186 | if(((buff.st_mode & S_IFMT)^S_IFCHR) == 0 || ((buff.st_mode & S_IFMT)^S_IFBLK) ==0) 187 | printf(" %6d %8s %8s %5d, %5d %13s %s\n",(int)buff.st_nlink,pw->pw_name,gp->gr_name,major(buff.st_rdev),minor(buff.st_rdev),time_buff,*(arg + i)); 188 | else 189 | printf(" %6d %8s %8s %12u %13s %s\n",(int)buff.st_nlink,pw->pw_name,gp->gr_name,(unsigned int)buff.st_size,time_buff,*(arg + i)); 190 | i++; 191 | } 192 | 193 | printf("total %d\n\n",val); 194 | closedir(fd); 195 | 196 | } 197 | 198 | -------------------------------------------------------------------------------- /Command line/list_content.h: -------------------------------------------------------------------------------- 1 | /* 2 | List the contents of current working directory on server (`ls` and `ls -l` linux commands). 3 | */ 4 | void list_content(char *arg, char *user_input, int sockfd) 5 | { 6 | /* Temporary variables */ 7 | int no_of_bytes; 8 | int port; 9 | int newsockfd; 10 | 11 | struct timeval tm;/* time structure to set time wait for receive buffer */ 12 | tm.tv_sec = 4; 13 | tm.tv_usec = 750000; 14 | 15 | char message_from_server[MAXSZ]; 16 | char message_to_server[MAXSZ]; 17 | 18 | /* Initialise character arrays */ 19 | bzero(message_from_server,MAXSZ); 20 | bzero(message_to_server,MAXSZ); 21 | 22 | /* Request server to start BINARY mode */ 23 | send(sockfd,"TYPE I\r\n",8,0); 24 | 25 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 26 | { 27 | message_from_server[no_of_bytes] = '\0'; 28 | printf("%s",message_from_server); 29 | fflush(stdout); 30 | if(strstr(message_from_server,"200 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"504 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 31 | break; 32 | } 33 | printf("\n"); 34 | 35 | if(strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"504 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 36 | return; 37 | 38 | /* Request server to connect to PASSIVE port for file transfers */ 39 | send(sockfd,passive,strlen(passive),0); 40 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 41 | { 42 | message_from_server[no_of_bytes] = '\0'; 43 | printf("%s",message_from_server); 44 | fflush(stdout); 45 | if(strstr(message_from_server,"227 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"502 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 46 | break; 47 | } 48 | printf("\n"); 49 | 50 | if(strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"502 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 51 | return; 52 | 53 | /* Request acepted. Connect to PASSIVE port */ 54 | if(strncmp(message_from_server,"227",3)== 0) 55 | { 56 | 57 | /* Generate PORT address */ 58 | port = passive_port_number(message_from_server); 59 | 60 | /* Create socket for PASSIVE connection */ 61 | newsockfd = func_to_connect_passive(arg,port); 62 | 63 | if(strcmp(user_input,"ls -l") == 0) 64 | sprintf(message_to_server,"LIST -l\r\n");/* ls -l */ 65 | else 66 | sprintf(message_to_server,"NLST\r\n");/* ls */ 67 | 68 | send(sockfd,message_to_server,strlen(message_to_server),0); 69 | 70 | 71 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 72 | { 73 | message_from_server[no_of_bytes] = '\0'; 74 | printf("%s",message_from_server); 75 | fflush(stdout); 76 | 77 | if(strstr(message_from_server,"425 ") > 0|| strstr(message_from_server,"125 ") > 0||strstr(message_from_server,"150 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"502 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 78 | break; 79 | } 80 | printf("\n"); 81 | 82 | if(strncmp(message_from_server,"125",3) != 0 && strncmp(message_from_server,"150",3) != 0) 83 | return; 84 | 85 | 86 | /* Read data on new PASSIVE socket */ 87 | 88 | while((no_of_bytes = recv(newsockfd,message_from_server,MAXSZ,0)) > 0) 89 | { 90 | message_from_server[no_of_bytes] = '\0'; 91 | printf("%s",message_from_server); 92 | fflush(stdout); 93 | 94 | } 95 | printf("\n"); 96 | 97 | close(newsockfd);/* Close PASSIVE connection */ 98 | 99 | /* Set time boundation on receive buffer */ 100 | setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO,(char *)&tm,sizeof(tm)); 101 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 102 | { 103 | message_from_server[no_of_bytes] = '\0'; 104 | printf("%s",message_from_server); 105 | fflush(stdout); 106 | if(strstr(message_from_server,"226 ") > 0) 107 | break; 108 | } 109 | printf("\n"); 110 | 111 | tm.tv_sec = 0; 112 | tm.tv_usec = 0; 113 | setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO,(char *)&tm,sizeof(tm)); 114 | } 115 | 116 | } 117 | 118 | -------------------------------------------------------------------------------- /Command line/passive_connect.h: -------------------------------------------------------------------------------- 1 | /* 2 | Generate a passive PORT number from the variables sent by server. 3 | */ 4 | int passive_port_number(char *message) 5 | { 6 | int i = INITIALISE; 7 | int count = INITIALISE; 8 | int port = INITIALISE; 9 | char *token; 10 | char delim[]=" ,)";/* Delimiters for strtok()*/ 11 | 12 | while(message[i] != '\0' && count < 4)/* To reach to th first PORT variable */ 13 | { 14 | if(message[i] == ',') 15 | { 16 | count++; 17 | } 18 | i++; 19 | } 20 | 21 | count = 0; 22 | 23 | token = strtok(message + i,delim); 24 | while(token != NULL) 25 | { 26 | if(isdigit(token[0])) 27 | { 28 | if(count == 1) 29 | { 30 | port += atoi(token); 31 | } 32 | 33 | if(count == 0) 34 | { 35 | port = atoi(token)*256; 36 | count++; 37 | } 38 | 39 | } 40 | token = strtok(NULL,delim); 41 | } 42 | return port; 43 | 44 | } 45 | 46 | /* Create PASSIVE socket and connect to server */ 47 | int func_to_connect_passive(char *address,int port) 48 | { 49 | int newsockfd; 50 | struct sockaddr_in new_serverAddress; 51 | 52 | newsockfd = socket(AF_INET,SOCK_STREAM,0); 53 | bzero(&new_serverAddress,sizeof(new_serverAddress)); 54 | 55 | new_serverAddress.sin_family = AF_INET; 56 | new_serverAddress.sin_addr.s_addr = inet_addr(address); 57 | new_serverAddress.sin_port = htons(port); 58 | 59 | connect(newsockfd,(struct sockaddr *)&new_serverAddress,sizeof(new_serverAddress)); 60 | 61 | return newsockfd; 62 | } 63 | -------------------------------------------------------------------------------- /Command line/put_content.h: -------------------------------------------------------------------------------- 1 | /* 2 | Upload files on server. 3 | */ 4 | void put_content(char *arg,char *user_input,int sockfd) 5 | { 6 | /* Temporary variables*/ 7 | int no_of_bytes; 8 | int port; 9 | int newsockfd; 10 | int fd; 11 | int p; 12 | int total; 13 | int size; 14 | 15 | struct timeval tm;/* time structure to set time wait for receive buffer */ 16 | tm.tv_sec = 1; 17 | tm.tv_usec = 750000; 18 | 19 | struct stat buff; 20 | 21 | char message_from_server[MAXSZ]; 22 | char message_to_server[MAXSZ]; 23 | char file[MAXSZ];// File name 24 | char file_name[MAXSZ];// File name with instruction to server 25 | char data[MAXSZ];// Data transfer 26 | 27 | /* Initialise all the character arrays */ 28 | bzero(message_from_server,MAXSZ); 29 | bzero(message_to_server,MAXSZ); 30 | bzero(file_name,MAXSZ); 31 | bzero(file,MAXSZ); 32 | bzero(data,MAXSZ); 33 | 34 | /* Tell server to change to BINARY mode */ 35 | send(sockfd,"TYPE I\r\n",8,0); 36 | 37 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 38 | { 39 | message_from_server[no_of_bytes] = '\0'; 40 | printf("%s",message_from_server); 41 | fflush(stdout); 42 | if(strstr(message_from_server,"200 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"504 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 43 | break; 44 | } 45 | printf("\n"); 46 | 47 | if(strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"504 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 48 | return; 49 | 50 | /* Send request for PASSIVE connection */ 51 | send(sockfd,passive,strlen(passive),0); 52 | 53 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 54 | { 55 | message_from_server[no_of_bytes] = '\0'; 56 | printf("%s",message_from_server); 57 | fflush(stdout); 58 | if(strstr(message_from_server,"227 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"502 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 59 | break; 60 | 61 | } 62 | printf("\n"); 63 | 64 | if(strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"502 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 65 | return; 66 | 67 | /* Server accepts request and sends PORT variables */ 68 | if(strncmp(message_from_server,"227",3) == 0) 69 | { 70 | /* Generate a PORT number using PORT variables */ 71 | port = passive_port_number(message_from_server); 72 | 73 | /* Connect to server using another PORT for file transfers */ 74 | newsockfd = func_to_connect_passive(arg,port); 75 | 76 | /* Send file name to server */ 77 | sprintf(file_name,"STOR %s\r\n",user_input + 4); 78 | send(sockfd,file_name,strlen(file_name),0); 79 | 80 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 81 | { 82 | message_from_server[no_of_bytes] = '\0'; 83 | printf("%s",message_from_server); 84 | fflush(stdout); 85 | if(strstr(message_from_server,"550 ") > 0 ||strstr(message_from_server,"125 ") > 0 ||strstr(message_from_server,"150 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"452 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0 || strstr(message_from_server,"553 ") > 0 ||strstr(message_from_server,"532 ") > 0) 86 | break; 87 | } 88 | printf("\n"); 89 | 90 | /* Send file data to server */ 91 | if(strncmp(message_from_server,"150",3) == 0 || strncmp(message_from_server,"125",3) == 0) 92 | { 93 | sprintf(file,"%s",user_input + 4); 94 | 95 | fd = open(file,O_RDONLY); 96 | fstat(fd,&buff); 97 | size = (int)buff.st_size; 98 | while(size > 0) 99 | { 100 | no_of_bytes = read(fd,data,MAXSZ); 101 | total = 0; 102 | while(total < no_of_bytes) 103 | { 104 | p = send(newsockfd,data + total,no_of_bytes - total,0); 105 | total += p; 106 | } 107 | size -= no_of_bytes; 108 | } 109 | 110 | close(newsockfd); 111 | /* Set time boundation on receive buffer */ 112 | setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO,(char *)&tm,sizeof(tm)); 113 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 114 | { 115 | message_from_server[no_of_bytes] = '\0'; 116 | printf("%s\n",message_from_server); 117 | fflush(stdout); 118 | if(strstr(message_from_server,"226 ") > 0) 119 | break; 120 | } 121 | } 122 | 123 | } 124 | } 125 | 126 | -------------------------------------------------------------------------------- /Command line/put_unique.h: -------------------------------------------------------------------------------- 1 | /* 2 | Upload files on server. 3 | */ 4 | void put_unique(char *arg,char *user_input,int sockfd) 5 | { 6 | /* Temporary variables*/ 7 | int no_of_bytes; 8 | int port; 9 | int newsockfd; 10 | int fd; 11 | int p; 12 | int total; 13 | int size; 14 | 15 | struct timeval tm;/* time structure to set time wait for receive buffer */ 16 | tm.tv_sec = 1; 17 | tm.tv_usec = 750000; 18 | 19 | struct stat buff; 20 | 21 | char message_from_server[MAXSZ]; 22 | char message_to_server[MAXSZ]; 23 | char file[MAXSZ];// File name 24 | char file_name[MAXSZ];// File name with instruction to server 25 | char data[MAXSZ];// Data transfer 26 | 27 | /* Initialise all the character arrays */ 28 | bzero(message_from_server,MAXSZ); 29 | bzero(message_to_server,MAXSZ); 30 | bzero(file_name,MAXSZ); 31 | bzero(file,MAXSZ); 32 | bzero(data,MAXSZ); 33 | 34 | /* Tell server to change to BINARY mode */ 35 | send(sockfd,"TYPE I\r\n",8,0); 36 | 37 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 38 | { 39 | message_from_server[no_of_bytes] = '\0'; 40 | printf("%s",message_from_server); 41 | fflush(stdout); 42 | if(strstr(message_from_server,"200 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"504 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 43 | break; 44 | } 45 | printf("\n"); 46 | 47 | if(strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"504 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 48 | return; 49 | 50 | /* Send request for PASSIVE connection */ 51 | send(sockfd,passive,strlen(passive),0); 52 | 53 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 54 | { 55 | message_from_server[no_of_bytes] = '\0'; 56 | printf("%s",message_from_server); 57 | fflush(stdout); 58 | if(strstr(message_from_server,"227 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"502 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 59 | break; 60 | 61 | } 62 | printf("\n"); 63 | 64 | if(strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"502 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 65 | return; 66 | 67 | /* Server accepts request and sends PORT variables */ 68 | if(strncmp(message_from_server,"227",3) == 0) 69 | { 70 | /* Generate a PORT number using PORT variables */ 71 | port = passive_port_number(message_from_server); 72 | 73 | /* Connect to server using another PORT for file transfers */ 74 | newsockfd = func_to_connect_passive(arg,port); 75 | 76 | /* Send file name to server */ 77 | sprintf(file_name,"STOU %s\r\n",user_input + 8); 78 | send(sockfd,file_name,strlen(file_name),0); 79 | 80 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 81 | { 82 | message_from_server[no_of_bytes] = '\0'; 83 | printf("%s",message_from_server); 84 | fflush(stdout); 85 | if(strstr(message_from_server,"550 ") > 0 ||strstr(message_from_server,"125 ") > 0 ||strstr(message_from_server,"150 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"452 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0 || strstr(message_from_server,"553 ") > 0 ||strstr(message_from_server,"532 ") > 0) 86 | break; 87 | } 88 | printf("\n"); 89 | 90 | /* Send file data to server */ 91 | if(strncmp(message_from_server,"150",3) == 0 || strncmp(message_from_server,"125",3) == 0) 92 | { 93 | sprintf(file,"%s",user_input + 4); 94 | 95 | fd = open(file,O_RDONLY); 96 | fstat(fd,&buff); 97 | size = (int)buff.st_size; 98 | while(size > 0) 99 | { 100 | no_of_bytes = read(fd,data,MAXSZ); 101 | total = 0; 102 | while(total < no_of_bytes) 103 | { 104 | p = send(newsockfd,data + total,no_of_bytes - total,0); 105 | total += p; 106 | } 107 | size -= no_of_bytes; 108 | } 109 | 110 | close(newsockfd); 111 | /* Set time boundation on receive buffer */ 112 | setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO,(char *)&tm,sizeof(tm)); 113 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 114 | { 115 | message_from_server[no_of_bytes] = '\0'; 116 | printf("%s\n",message_from_server); 117 | fflush(stdout); 118 | if(strstr(message_from_server,"226 ") > 0) 119 | break; 120 | } 121 | } 122 | 123 | } 124 | } 125 | 126 | -------------------------------------------------------------------------------- /Command line/thread_get.h: -------------------------------------------------------------------------------- 1 | /* 2 | Each thread will establish an instruction connection and a passive connection to server. 3 | */ 4 | void *function(void *point) 5 | { 6 | int sockfd; 7 | int temp = 0; 8 | int no_of_bytes; 9 | int newsockfd; 10 | int fd; 11 | int port; 12 | int total; 13 | int p; 14 | int size; 15 | int temp_size; 16 | 17 | struct sockaddr_in serverAddress; 18 | 19 | struct userdetails *obj; 20 | obj = (struct userdetails *)point; 21 | 22 | char message_from_server[MAXSZ]; 23 | char message_to_server[MAXSZ]; 24 | char data[MAXSZ]; 25 | char file[MAXSZ];// File name 26 | char file_name[MAXSZ];// File name with instruction to server 27 | char file_home_dir[MAXSZ];// Location of file i.e. User's home directory(Complete path to file). 28 | 29 | /* Initialise all the character arrays */ 30 | bzero(message_from_server,MAXSZ); 31 | bzero(message_to_server,MAXSZ); 32 | bzero(file_name,MAXSZ); 33 | bzero(file,MAXSZ); 34 | bzero(file_home_dir,MAXSZ); 35 | bzero(data,MAXSZ); 36 | 37 | sockfd = socket(AF_INET,SOCK_STREAM,0); 38 | 39 | bzero(&serverAddress,sizeof(serverAddress));/* Initialise structure */ 40 | 41 | serverAddress.sin_family = AF_INET; 42 | serverAddress.sin_addr.s_addr = inet_addr(obj->arg); 43 | serverAddress.sin_port = htons(PORT); 44 | 45 | /* Connect to server */ 46 | connect(sockfd,(struct sockaddr *)&serverAddress,sizeof(serverAddress)); 47 | /* if(connect_value == -1)// Connection Error 48 | { 49 | perror("Error"); 50 | exit(1); 51 | } 52 | 53 | */ 54 | /* Receive message from server "Server will send 220" */ 55 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0 ) 56 | { 57 | message_from_server[no_of_bytes] = '\0'; 58 | 59 | if(strstr(message_from_server,"220 ") > 0 || strstr(message_from_server,"421 ") > 0) 60 | break; 61 | } 62 | 63 | send(sockfd,user,strlen(user),0);/* Send username to server */ 64 | 65 | 66 | /* 67 | Receive message from server after sending user name. 68 | Message with code 331 asks you to enter password corresponding to user. 69 | Message with code 230 means no password is required for the entered username(LOGIN successful). 70 | */ 71 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 72 | { 73 | message_from_server[no_of_bytes] = '\0'; 74 | if(strncmp(message_from_server,"331",3) == 0) 75 | { 76 | temp = 1; 77 | } 78 | 79 | if(strncmp(message_from_server,"230",3) == 0) 80 | { 81 | temp = 2; 82 | } 83 | 84 | if(strncmp(message_from_server,"530",3) == 0) 85 | { 86 | temp = 0; 87 | } 88 | if(strstr(message_from_server,"230 ") > 0 || strstr(message_from_server,"500 ") > 0 || strstr(message_from_server,"501 ") > 0 || strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"332 ") > 0 || strstr(message_from_server,"530 ")|| strstr(message_from_server,"331 ") > 0) 89 | break; 90 | } 91 | 92 | if(temp == 1)//Password is required for server 93 | { 94 | send(sockfd,pass,strlen(pass),0);/* Send password to server */ 95 | 96 | /* Receive message from server */ 97 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 98 | { 99 | message_from_server[no_of_bytes] = '\0'; 100 | 101 | if(strstr(message_from_server,"230 ") > 0 || strstr(message_from_server,"500 ") > 0 || strstr(message_from_server,"501 ") > 0 || strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"332 ") > 0 || strstr(message_from_server,"530 ")|| strstr(message_from_server,"503 ") > 0 || strstr(message_from_server,"202 ") > 0) 102 | break; 103 | 104 | } 105 | } 106 | 107 | 108 | /* Tell server to change to BINARY mode */ 109 | send(sockfd,"TYPE I\r\n",8,0); 110 | 111 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 112 | { 113 | message_from_server[no_of_bytes] = '\0'; 114 | if(strstr(message_from_server,"200 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"504 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 115 | break; 116 | } 117 | 118 | 119 | /* Send request for PASSIVE connection */ 120 | send(sockfd,passive,strlen(passive),0); 121 | 122 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 123 | { 124 | message_from_server[no_of_bytes] = '\0'; 125 | if(strstr(message_from_server,"227 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"502 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 126 | break; 127 | } 128 | 129 | /* Server accepts request and sends PORT variables */ 130 | if(strncmp(message_from_server,"227",3) == 0) 131 | { 132 | /* Generate a PORT number using PORT variables */ 133 | port = passive_port_number(message_from_server); 134 | 135 | /* Connect to server using another PORT for file transfers */ 136 | newsockfd = func_to_connect_passive(obj->arg,port); 137 | 138 | sprintf(message_to_server,"REST %d\r\n",(obj->t_id)*(obj->size));//Starting byte of chunk of data that is required 139 | 140 | send(sockfd,message_to_server,strlen(message_to_server),0); 141 | 142 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 143 | { 144 | message_from_server[no_of_bytes] = '\0'; 145 | if(strstr(message_from_server,"350 ") > 0 || strstr(message_from_server,"500 ") > 0 || strstr(message_from_server,"501 ") > 0 || strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"502 ") > 0 || strstr(message_from_server,"530 ")) 146 | break; 147 | } 148 | 149 | sprintf(file,"%s",(obj->user_input) + 4); 150 | 151 | 152 | /* Send file name */ 153 | sprintf(file_name,"RETR %s/%s\r\n",obj->pwd,(obj->user_input) + 4); 154 | send(sockfd,file_name,strlen(file_name),0); 155 | 156 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 157 | { 158 | message_from_server[no_of_bytes] = '\0'; 159 | if(strstr(message_from_server,"425 ") > 0|| strstr(message_from_server,"125 ") > 0 ||strstr(message_from_server,"150 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"550 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 160 | break; 161 | } 162 | 163 | sprintf(file_home_dir,"%s/%s%d",obj->home_dir,file,obj->t_id); 164 | 165 | /* Create file on client system */ 166 | fd = open(file_home_dir,O_CREAT|O_WRONLY|O_TRUNC,0644); 167 | size = 0; 168 | while((no_of_bytes = recv(newsockfd,data,MAXSZ,0))>0)//Get specific chunk of data 169 | { 170 | if(size >= obj->size) 171 | break; 172 | 173 | size += no_of_bytes; 174 | if(size > obj->size) 175 | { 176 | temp_size = no_of_bytes - (size - obj->size); 177 | 178 | size -= no_of_bytes; 179 | size += temp_size; 180 | no_of_bytes = temp_size; 181 | } 182 | 183 | total = 0; 184 | /* For partial write operations */ 185 | while(total < no_of_bytes) 186 | { 187 | p = write(fd,data + total,no_of_bytes - total); 188 | total += p; 189 | } 190 | 191 | } 192 | 193 | 194 | /* Close PASSIVE socket and file */ 195 | close(newsockfd); 196 | close(fd); 197 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 198 | { 199 | message_from_server[no_of_bytes] = '\0'; 200 | if(strstr(message_from_server,"226 ") > 0 || strstr(message_from_server,"426 ") > 0) 201 | break; 202 | } 203 | 204 | } 205 | close(sockfd);//Close connection 206 | pthread_exit((void *)point); 207 | } 208 | -------------------------------------------------------------------------------- /GUI/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | FLG=-c -Wall 3 | 4 | all: ftp_graphic 5 | 6 | ftp_graphic: gtk_final.o 7 | @$(CC) gtk_final.o -o ftp_graphic `pkg-config --cflags --libs gtk+-2.0 gthread-2.0` -lpthread 8 | 9 | gtk_final.o: gtk_final.c 10 | @$(CC) $(FLG) gtk_final.c `pkg-config --cflags --libs gtk+-2.0 gthread-2.0` -lpthread 11 | 12 | clean: 13 | @rm *.o 14 | -------------------------------------------------------------------------------- /GUI/Screenshots/myftp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohit-takhar/Multithreaded-ftp-client-in-C/7bd675534d2fbaa1ff36c60fc225a1e91d7d1498/GUI/Screenshots/myftp.png -------------------------------------------------------------------------------- /GUI/Screenshots/myftp1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohit-takhar/Multithreaded-ftp-client-in-C/7bd675534d2fbaa1ff36c60fc225a1e91d7d1498/GUI/Screenshots/myftp1.png -------------------------------------------------------------------------------- /GUI/back1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohit-takhar/Multithreaded-ftp-client-in-C/7bd675534d2fbaa1ff36c60fc225a1e91d7d1498/GUI/back1.png -------------------------------------------------------------------------------- /GUI/get_content.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Download files from server. 4 | */ 5 | 6 | void *get_content(void *thread_data) 7 | { 8 | 9 | struct data *my_data; 10 | my_data = (struct data *)thread_data; 11 | 12 | char *arg = my_data->argv1; 13 | char *user_input = my_data->user_data; 14 | Appstate *app_state = my_data->app_state; 15 | 16 | /* Temporary variables*/ 17 | int no_of_bytes; 18 | int port; 19 | int newsockfd; 20 | int i; 21 | int j = 0; 22 | int count = 0; 23 | int size; 24 | int no_of_threads; 25 | int total; 26 | int partial_bytes; 27 | int filehandle; 28 | int fd; 29 | int retry = 0; 30 | int error_val = 0; 31 | 32 | clock_t start,end; 33 | double cpu_time; 34 | 35 | char message_from_server[MAXSZ]; 36 | char message_to_server[MAXSZ]; 37 | char file[MAXSZ];// File name 38 | char file_name[MAXSZ];// File name with instruction to server 39 | char data[MAXSZ];// Data transfer 40 | char pwd[MAXSZ]; 41 | char size_file[MAXSZ];// size of file 42 | char temp_file[MAXSZ];//temporary files created on client side 43 | 44 | struct stat file_buff; 45 | 46 | /* Initialise all the character arrays */ 47 | bzero(message_from_server,MAXSZ); 48 | bzero(message_to_server,MAXSZ); 49 | bzero(file_name,MAXSZ); 50 | bzero(file,MAXSZ); 51 | bzero(data,MAXSZ); 52 | bzero(pwd,MAXSZ); 53 | bzero(size_file,MAXSZ); 54 | bzero(temp_file,MAXSZ); 55 | bzero(buff,MAXSZ1); 56 | 57 | /* Getting file size from server*/ 58 | sprintf(size_file,"SIZE %s\r\n",user_input + 4); 59 | send(app_state->sockfd,size_file,strlen(size_file),0); 60 | 61 | error_val = 0; 62 | retry = 0; 63 | while((no_of_bytes = recv(app_state->sockfd,message_from_server,MAXSZ,0)) > 0) 64 | { 65 | if(no_of_bytes == 0) 66 | { 67 | if(retry < 3) 68 | { 69 | retry++; 70 | continue; 71 | } 72 | else 73 | { 74 | error_val = 1; 75 | break; 76 | } 77 | 78 | } 79 | 80 | message_from_server[no_of_bytes] = '\0'; 81 | if(strstr(message_from_server,"213 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"502 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"550 ") > 0) 82 | break; 83 | } 84 | 85 | if(error_val == 1) 86 | { 87 | sprintf(buff,"Error in downloading! Try again.\n"); 88 | print_buff(app_state); 89 | global_val = 1; 90 | pthread_exit(NULL); 91 | } 92 | 93 | size = atoi(message_from_server + 4);/* Converting string to integer */ 94 | 95 | /* Getting current working dirctory */ 96 | send(app_state->sockfd,"PWD\r\n",5,0); 97 | 98 | error_val = 0; 99 | retry = 0; 100 | while((no_of_bytes = recv(app_state->sockfd,message_from_server,MAXSZ,0)) > 0) 101 | { 102 | if(no_of_bytes == 0) 103 | { 104 | if(retry < 3) 105 | { 106 | retry++; 107 | continue; 108 | } 109 | else 110 | { 111 | error_val = 1; 112 | break; 113 | } 114 | 115 | } 116 | 117 | message_from_server[no_of_bytes] = '\0'; 118 | if(strstr(message_from_server,"257 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"502 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"550 ") > 0) 119 | break; 120 | } 121 | 122 | if(error_val == 1) 123 | { 124 | sprintf(buff,"Error in downloading! Try again.\n"); 125 | print_buff(app_state); 126 | global_val = 1; 127 | pthread_exit(NULL); 128 | } 129 | 130 | /* Exract current working directory name from the message */ 131 | for(i = 0; message_from_server[i]!='\0';i++) 132 | { 133 | if(message_from_server[i] == '\"' && count == 1) 134 | { 135 | break; 136 | } 137 | 138 | if(count == 1) 139 | { 140 | pwd[j++] = message_from_server[i]; 141 | } 142 | 143 | if(message_from_server[i] == '\"' && count == 0) 144 | { 145 | count = 1; 146 | } 147 | 148 | } 149 | pwd[j] = '\0'; 150 | 151 | 152 | /* Tell server to change to BINARY mode */ 153 | send(app_state->sockfd,"TYPE I\r\n",8,0); 154 | sprintf(buff,"Command: TYPE I\nResponse: "); 155 | print_buff(app_state); 156 | 157 | retry = 0; 158 | error_val = 0; 159 | while((no_of_bytes = recv(app_state->sockfd,message_from_server,MAXSZ,0)) > 0) 160 | { 161 | if(no_of_bytes == 0) 162 | { 163 | if(retry < 3) 164 | { 165 | retry++; 166 | continue; 167 | } 168 | else 169 | { 170 | error_val = 1; 171 | break; 172 | } 173 | 174 | } 175 | 176 | message_from_server[no_of_bytes] = '\0'; 177 | sprintf(buff,"%s",message_from_server); 178 | print_buff(app_state); 179 | 180 | if(strstr(message_from_server,"200 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"504 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 181 | break; 182 | } 183 | sprintf(buff,"\n"); 184 | print_buff(app_state); 185 | if(error_val == 1) 186 | { 187 | sprintf(buff,"Error in downloading! Try again.\n"); 188 | print_buff(app_state); 189 | global_val = 1; 190 | pthread_exit(NULL); 191 | } 192 | 193 | 194 | if(strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"504 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 195 | { 196 | global_val = 1; 197 | pthread_exit(NULL); 198 | // return; 199 | } 200 | /* Send request for PASSIVE connection */ 201 | send(app_state->sockfd,passive,strlen(passive),0); 202 | sprintf(buff,"Command: %sResponse: ",passive); 203 | print_buff(app_state); 204 | error_val = 0; 205 | retry = 0; 206 | while((no_of_bytes = recv(app_state->sockfd,message_from_server,MAXSZ,0)) > 0) 207 | { 208 | if(no_of_bytes == 0) 209 | { 210 | if(retry < 3) 211 | { 212 | retry++; 213 | continue; 214 | } 215 | else 216 | { 217 | error_val = 1; 218 | break; 219 | } 220 | 221 | } 222 | 223 | message_from_server[no_of_bytes] = '\0'; 224 | sprintf(buff,"%s",message_from_server); 225 | print_buff(app_state); 226 | 227 | if(strstr(message_from_server,"227 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"502 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 228 | break; 229 | } 230 | 231 | sprintf(buff,"\n"); 232 | print_buff(app_state); 233 | if(error_val == 1) 234 | { 235 | sprintf(buff,"Error in downloading! Try again.\n"); 236 | print_buff(app_state); 237 | global_val = 1; 238 | pthread_exit(NULL); 239 | } 240 | 241 | 242 | if(strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"502 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 243 | { 244 | global_val = 1; 245 | pthread_exit(NULL); 246 | //return; 247 | } 248 | /* Server accepts request and sends PORT variables */ 249 | if(strncmp(message_from_server,"227",3) == 0) 250 | { 251 | /* Generate a PORT number using PORT variables */ 252 | port = passive_port_number(message_from_server); 253 | 254 | /* Connect to server using another PORT for file transfers */ 255 | newsockfd = func_to_connect_passive(arg,port); 256 | // fcntl(newsockfd,F_SETFL,FNDELAY); 257 | 258 | sprintf(file,"%s",user_input + 4); 259 | 260 | /* Send file name */ 261 | sprintf(file_name,"RETR %s\r\n",user_input + 4); 262 | sprintf(buff,"Command: RETR %s\nResponse: ",user_input + 4); 263 | print_buff(app_state); 264 | 265 | send(app_state->sockfd,file_name,strlen(file_name),0); 266 | retry = 0; 267 | error_val = 0; 268 | while((no_of_bytes = recv(app_state->sockfd,message_from_server,MAXSZ,0)) > 0) 269 | { 270 | if(no_of_bytes == 0) 271 | { 272 | if(retry < 3) 273 | { 274 | retry++; 275 | continue; 276 | } 277 | else 278 | { 279 | error_val = 1; 280 | break; 281 | } 282 | 283 | } 284 | 285 | message_from_server[no_of_bytes] = '\0'; 286 | sprintf(buff,"%s",message_from_server); 287 | print_buff(app_state); 288 | 289 | if(strstr(message_from_server,"425 ") > 0|| strstr(message_from_server,"125 ") > 0 ||strstr(message_from_server,"150 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"550 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 290 | break; 291 | } 292 | sprintf(buff,"\n"); 293 | print_buff(app_state); 294 | if(error_val == 1) 295 | { 296 | sprintf(buff,"Error in downloading! Try again.\n"); 297 | print_buff(app_state); 298 | global_val = 1; 299 | pthread_exit(NULL); 300 | } 301 | 302 | 303 | 304 | /* Permission Denied */ 305 | if(strncmp(message_from_server,"550",3) == 0 || strncmp(message_from_server,"425",3) == 0) 306 | { 307 | close(newsockfd); 308 | // return; 309 | global_val = 1; 310 | pthread_exit(NULL); 311 | } 312 | else 313 | { 314 | /* Create file on client system */ 315 | filehandle = open(file,O_CREAT|O_WRONLY|O_TRUNC,0644); 316 | 317 | /* Decide total number of threads to be created */ 318 | if(size <= 150000) 319 | no_of_threads = 1; 320 | else if(size > 150000 && size < 1000000) 321 | no_of_threads = 5; 322 | else 323 | no_of_threads = 10; 324 | 325 | if(no_of_threads > 1)// Multithreading 326 | { 327 | /* initilise structure for each thread */ 328 | struct userdetails user[no_of_threads]; 329 | pthread_t thre[no_of_threads]; 330 | pthread_attr_t attr; 331 | pthread_attr_init(&attr); 332 | pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE); 333 | 334 | 335 | for(i = 0;i < no_of_threads;i++)// Initialise structures 336 | { 337 | strcpy(user[i].arg,arg); 338 | strcpy(user[i].user_input,user_input); 339 | strcpy(user[i].pwd,pwd); 340 | if(size % no_of_threads == 0) 341 | user[i].size = size/no_of_threads; 342 | else 343 | user[i].size = size/no_of_threads + 1; 344 | } 345 | 346 | start = clock(); 347 | 348 | for( i = 0;i < no_of_threads;i++)// Create threads 349 | { 350 | user[i].t_id = i; 351 | pthread_create(&thre[i],&attr,function,(void *)&user[i]); 352 | 353 | } 354 | 355 | sprintf(buff,"Downloading...\n"); 356 | print_buff(app_state); 357 | 358 | pthread_attr_destroy(&attr); 359 | for(i = 0;i < no_of_threads;i++)// Wait for completion of all threads 360 | { 361 | pthread_join(thre[i],NULL); 362 | } 363 | 364 | i = 0; 365 | total = 0; 366 | error_val = 0; 367 | while(i < no_of_threads) 368 | { 369 | sprintf(temp_file,"%s%d",user_input + 4,i); 370 | if(lstat(temp_file,&file_buff) == -1) 371 | { 372 | error_val = 1; 373 | break; 374 | } 375 | if(i < (no_of_threads -1)) 376 | { 377 | if(user[i].size == (int)file_buff.st_size) 378 | { 379 | total += (int)file_buff.st_size; 380 | i++; 381 | } 382 | else 383 | { 384 | error_val = 1; 385 | break; 386 | } 387 | } 388 | else 389 | { 390 | if(file_buff.st_size == (size - total)) 391 | { 392 | i++; 393 | } 394 | else 395 | { 396 | error_val = 1; 397 | break; 398 | } 399 | } 400 | } 401 | 402 | if(error_val == 1) 403 | { 404 | i = 0; 405 | while(i < no_of_threads) 406 | { 407 | sprintf(temp_file,"%s%d",user_input + 4,i); 408 | unlink(temp_file); 409 | i++; 410 | } 411 | 412 | sprintf(buff,"Error in downloading! Try again.\n"); 413 | print_buff(app_state); 414 | global_val = 1; 415 | pthread_exit(NULL); 416 | } 417 | 418 | sprintf(buff,"Downloading Completed\n"); 419 | print_buff(app_state); 420 | 421 | close(newsockfd);// Close passive connection 422 | while((no_of_bytes = recv(app_state->sockfd,message_from_server,MAXSZ,0)) > 0)//Server might send an error message. We can ignore this. 423 | { 424 | message_from_server[no_of_bytes] = '\0'; 425 | if(strstr(message_from_server,"450 ") > 0 ||strstr(message_from_server,"451 ") > 0 || strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"226 ") > 0 || strstr(message_from_server,"426 ") > 0) 426 | break; 427 | } 428 | 429 | sprintf(buff,"Combining data...\n"); 430 | print_buff(app_state); 431 | 432 | for(i = 0; i < no_of_threads; i++)//Joining temporary files 433 | { 434 | sprintf(temp_file,"%s%d",user_input + 4,i); 435 | fd = open(temp_file,O_RDONLY); 436 | 437 | while((no_of_bytes = read(fd,data,MAXSZ)) > 0) 438 | { 439 | data[no_of_bytes] = '\0'; 440 | total = 0; 441 | while(total < no_of_bytes) 442 | { 443 | partial_bytes = write(filehandle,data + total,no_of_bytes - total); 444 | total += partial_bytes; 445 | } 446 | bzero(data,MAXSZ); 447 | } 448 | close(fd); 449 | unlink(temp_file); 450 | } 451 | end = clock(); 452 | close(filehandle); 453 | sprintf(buff,"226 Transfer completed\n\n"); 454 | print_buff(app_state); 455 | 456 | cpu_time = ((double)(end - start))/CLOCKS_PER_SEC; 457 | sprintf(buff,"Time taken %lf\n\n",cpu_time); 458 | print_buff(app_state); 459 | 460 | 461 | 462 | } 463 | else//if file size is small. No need of multithreading 464 | { 465 | while((no_of_bytes = recv(newsockfd,data,MAXSZ,0))>0)//get data on passive connection 466 | { 467 | total = 0; 468 | if(no_of_bytes == 0) 469 | { 470 | if(retry < 3) 471 | { 472 | retry++; 473 | continue; 474 | } 475 | else 476 | { 477 | error_val = 1; 478 | break; 479 | } 480 | } 481 | 482 | /* For partial write operations */ 483 | while(total < no_of_bytes) 484 | { 485 | partial_bytes = write(filehandle,data + total,no_of_bytes - total); 486 | total += partial_bytes; 487 | } 488 | } 489 | 490 | /* Close PASSIVE socket and file */ 491 | close(newsockfd); 492 | close(filehandle); 493 | 494 | if(error_val == 1) 495 | { 496 | sprintf(buff,"Error in downloading! Try again.\n"); 497 | print_buff(app_state); 498 | global_val = 1; 499 | pthread_exit(NULL); 500 | } 501 | 502 | while((no_of_bytes = recv(app_state->sockfd,message_from_server,MAXSZ,0))>0) 503 | { 504 | if(no_of_bytes == 0) 505 | { 506 | if(retry < 3) 507 | { 508 | retry++; 509 | continue; 510 | } 511 | else 512 | { 513 | error_val = 1; 514 | break; 515 | } 516 | 517 | } 518 | 519 | message_from_server[no_of_bytes] = '\0'; 520 | sprintf(buff,"%s",message_from_server); 521 | print_buff(app_state); 522 | 523 | if(strstr(message_from_server,"226 ") > 0 || strstr(message_from_server,"426 ") > 0) 524 | break; 525 | } 526 | sprintf(buff,"\n"); 527 | print_buff(app_state); 528 | if(error_val == 1) 529 | { 530 | sprintf(buff,"Error in downloading! Try again.\n"); 531 | print_buff(app_state); 532 | global_val = 1; 533 | pthread_exit(NULL); 534 | } 535 | 536 | 537 | } 538 | } 539 | } 540 | global_val = 1; 541 | pthread_exit(NULL); 542 | } 543 | 544 | -------------------------------------------------------------------------------- /GUI/header.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include//socket 4 | #include//socket 5 | #include//sizeof 6 | #include 7 | #include 8 | #include 9 | #include//isdigit() 10 | #include//open() 11 | #include 12 | #include//stat() 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #define PORT 21 24 | #define MAXSZ 4096 25 | #define MAXSZ1 5000 26 | 27 | #define MIN_VALUE -1 28 | #define INITIALISE 0 29 | #define MIN_IP 0 30 | #define MAX_IP 255 31 | 32 | #define BUTTON_WIDTH 95 33 | #define BUTTON_HEIGHT 30 34 | 35 | char user[MAXSZ];/* user details sent to server */ 36 | char pass[MAXSZ];/* password details sent to server */ 37 | char buff[MAXSZ1]; 38 | char passive[]="PASV\r\n"; 39 | int global_val = 0; 40 | 41 | GtkTextBuffer *buffer; 42 | 43 | typedef struct _Appstate 44 | { 45 | GtkWidget *window; 46 | GtkWidget *entry; 47 | GtkWidget *entry_dir; 48 | GtkWidget *entry_dir_cli; 49 | GtkWidget *text_view; 50 | GtkWidget *view; 51 | GtkWidget *view1; 52 | GtkWidget *user; 53 | GtkWidget *password; 54 | GtkWidget *fileselect; 55 | GtkWidget *button; 56 | GtkWidget *ok_file_button; 57 | GtkWidget *ok_button; 58 | GtkWidget *command; 59 | int status; 60 | int sockfd; 61 | int running; 62 | int seek; 63 | int seek_cli; 64 | int temp_file_descriptor; 65 | int temp_file_descriptor_cli; 66 | }Appstate; 67 | 68 | struct userdetails 69 | { 70 | char arg[MAXSZ]; 71 | char user_input[MAXSZ]; 72 | char pwd[MAXSZ]; 73 | int t_id; 74 | int size; 75 | Appstate app_state; 76 | }; 77 | 78 | 79 | char temporary_file[]="/tmp/myTMP-XXXXXX";//Temporary file to store file names on server 80 | char temporary_file_cli[]="/tmp/myTMPcli-XXXXXX";//Temporary file to store file names on client 81 | 82 | enum 83 | { 84 | COL_PERM = 0, 85 | COL_NAME, 86 | COL_SIZE, 87 | COL_MOD, 88 | NUM_COLS 89 | }; 90 | 91 | extern int h_errno; 92 | int drag_same_side = 0; 93 | static const GtkTargetEntry drag_targets = { 94 | "STRING", GTK_TARGET_SAME_APP,0 95 | }; 96 | 97 | static guint n_targets = 1; 98 | 99 | struct DATA 100 | { 101 | char *perm; 102 | char *name; 103 | char *size; 104 | char *date; 105 | }; 106 | 107 | Appstate app_state; 108 | 109 | struct data 110 | { 111 | char *argv1; 112 | char *user_data; 113 | Appstate *app_state; 114 | }; 115 | struct data strrr; 116 | 117 | 118 | -------------------------------------------------------------------------------- /GUI/list_client.h: -------------------------------------------------------------------------------- 1 | /* 2 | List files in current working directory on client side. 3 | */ 4 | 5 | /* Return result of character comparison(Ignoring LETTER CASE)*/ 6 | int mycompare(const void *a, const void *b) 7 | { 8 | return strcasecmp(*(const char **)a,*(const char **)b); 9 | } 10 | 11 | 12 | /* `ls` comand in linux. List files in current working directory without details.*/ 13 | void ls_dir(Appstate *app_state,char *dir_name) 14 | { 15 | DIR *fd; 16 | 17 | char *arg[MAXSZ]; 18 | 19 | int i = INITIALISE; 20 | int n; 21 | 22 | struct dirent *entry; 23 | fd = opendir(dir_name);/* Open directory */ 24 | if(fd == NULL) 25 | { 26 | sprintf(buff,"Error: %s\n",strerror(errno)); 27 | print_buff(app_state); 28 | 29 | return; 30 | } 31 | 32 | while((entry = readdir(fd))!=NULL)/* Ignore hidden files */ 33 | { 34 | if(entry->d_name[0] != '.' && strcmp(entry->d_name,".") != 0 && strcmp(entry->d_name,"..") != 0) 35 | { 36 | *(arg + i) = entry->d_name; 37 | i++; 38 | } 39 | } 40 | 41 | n = i; 42 | 43 | qsort(arg,n,sizeof(const char *),mycompare);/* Sort file names in alphabetical order ignoring LETTER CASE*/ 44 | 45 | i = 0; 46 | sprintf(buff,"Here comes the directory listing\n\n"); 47 | print_buff(app_state); 48 | while(i < n) 49 | { 50 | sprintf(buff,"%s\n",*(arg + i)); 51 | print_buff(app_state); 52 | 53 | i++; 54 | } 55 | sprintf(buff,"\n"); 56 | print_buff(app_state); 57 | 58 | bzero(buff,MAXSZ1); 59 | closedir(fd); 60 | } 61 | 62 | void ls_l_dir(Appstate *app_state,char *dir_name) 63 | { 64 | char time_buff[MAXSZ]; 65 | char *arg[MAXSZ]; 66 | 67 | int i = INITIALISE; 68 | int n; 69 | int val = INITIALISE; 70 | int temp; 71 | 72 | struct group *gp;/* structure contaning group details */ 73 | struct passwd *pw;/* structure containing passwd file */ 74 | struct tm *info; 75 | struct stat file_buff; 76 | struct dirent *entry; 77 | DIR *fd; 78 | fd = opendir(dir_name);/* Open directory */ 79 | if(fd == NULL) 80 | { 81 | sprintf(buff,"Error: %s\n",strerror(errno)); 82 | print_buff(app_state); 83 | 84 | return; 85 | } 86 | 87 | while((entry = readdir(fd))!= NULL)/* Read directory */ 88 | { 89 | 90 | /* Call kiya tha */ 91 | if(strcmp(entry->d_name,".") != 0 && strcmp(entry->d_name,"..") != 0 && entry->d_name[0]!= '.') 92 | { 93 | *(arg + i) = entry->d_name; 94 | i++; 95 | } 96 | 97 | } 98 | 99 | n = i; 100 | qsort(arg,n,sizeof(const char *),mycompare); 101 | 102 | i = 0; 103 | sprintf(buff,"Here comes the directory listing\n\n"); 104 | print_buff(app_state); 105 | while(i < n) 106 | { 107 | lstat(*(arg + i),&file_buff); 108 | gp = getgrgid(file_buff.st_gid); 109 | pw = getpwuid(file_buff.st_uid); 110 | info = localtime(&(file_buff.st_mtime)); 111 | strftime(time_buff,sizeof(time_buff),"%b %d %H:%M",info); 112 | 113 | if(file_buff.st_size % 1024 == 0) 114 | { 115 | temp = (int)file_buff.st_size / 1024; 116 | val += temp ; 117 | } 118 | else 119 | { 120 | temp = ((int)file_buff.st_size / 1024); 121 | val += (temp + (4 - (temp % 4))); 122 | } 123 | 124 | /* Selecting file type */ 125 | switch(file_buff.st_mode & S_IFMT) 126 | { 127 | case S_IFCHR: 128 | sprintf(buff,"c"); 129 | break; 130 | case S_IFBLK: 131 | sprintf(buff,"b"); 132 | break; 133 | case S_IFDIR: 134 | sprintf(buff,"d"); 135 | break; 136 | case S_IFLNK: 137 | sprintf(buff,"l"); 138 | break; 139 | case S_IFIFO: 140 | sprintf(buff,"p"); 141 | break; 142 | case S_IFSOCK: 143 | sprintf(buff,"s"); 144 | break; 145 | default: 146 | sprintf(buff,"-"); 147 | break; 148 | } 149 | 150 | print_buff(app_state); 151 | 152 | /* File permissions */ 153 | if(file_buff.st_mode & S_IRUSR) 154 | sprintf(buff,"r"); 155 | else 156 | sprintf(buff,"-"); 157 | 158 | if(file_buff.st_mode & S_IWUSR) 159 | strcat(buff,"w"); 160 | else 161 | strcat(buff,"-"); 162 | 163 | if(file_buff.st_mode & S_IXUSR) 164 | strcat(buff,"x"); 165 | else 166 | strcat(buff,"-"); 167 | 168 | if(file_buff.st_mode & S_IRGRP) 169 | strcat(buff,"r"); 170 | else 171 | strcat(buff,"-"); 172 | 173 | if(file_buff.st_mode & S_IWGRP) 174 | strcat(buff,"w"); 175 | else 176 | strcat(buff,"-"); 177 | 178 | if(file_buff.st_mode & S_IXGRP) 179 | strcat(buff,"x"); 180 | else 181 | strcat(buff,"-"); 182 | 183 | if(file_buff.st_mode & S_IROTH) 184 | strcat(buff,"r"); 185 | else 186 | strcat(buff,"-"); 187 | 188 | if(file_buff.st_mode & S_IWOTH) 189 | strcat(buff,"w"); 190 | else 191 | strcat(buff,"-"); 192 | 193 | if(file_buff.st_mode & S_IXOTH) 194 | strcat(buff,"x"); 195 | else 196 | strcat(buff,"-"); 197 | 198 | print_buff(app_state); 199 | 200 | if(((file_buff.st_mode & S_IFMT)^S_IFCHR) == 0 || ((file_buff.st_mode & S_IFMT)^S_IFBLK) ==0) 201 | sprintf(buff," %9d %20s %20s %8d, %8d %15s %25s\n",(int)file_buff.st_nlink,pw->pw_name,gp->gr_name,major(file_buff.st_rdev),minor(file_buff.st_rdev),time_buff,*(arg + i)); 202 | else 203 | sprintf(buff," %9d %20s %20s %18u %15s %25s\n",(int)file_buff.st_nlink,pw->pw_name,gp->gr_name,(unsigned int)file_buff.st_size,time_buff,*(arg + i)); 204 | 205 | print_buff(app_state); 206 | i++; 207 | } 208 | 209 | sprintf(buff,"total %d\n\n",val); 210 | print_buff(app_state); 211 | 212 | bzero(buff,MAXSZ1); 213 | closedir(fd); 214 | 215 | } 216 | 217 | 218 | void ls_l_dir_view(Appstate *app_state,char *dir_name) 219 | { 220 | char time_buff[MAXSZ]; 221 | char *arg[MAXSZ]; 222 | char data[MAXSZ]; 223 | 224 | int i = INITIALISE; 225 | int n; 226 | 227 | struct group *gp;/* structure contaning group details */ 228 | struct passwd *pw;/* structure containing passwd file */ 229 | struct tm *info; 230 | struct stat file_buff; 231 | struct dirent *entry; 232 | DIR *fd; 233 | fd = opendir(dir_name);/* Open directory */ 234 | if(fd == NULL) 235 | { 236 | return; 237 | } 238 | 239 | while((entry = readdir(fd))!= NULL)/* Read directory */ 240 | { 241 | 242 | if(entry->d_name[0] != '.') 243 | { 244 | *(arg + i) = entry->d_name; 245 | i++; 246 | } 247 | 248 | // while(gtk_events_pending()) 249 | // gtk_main_iteration(); 250 | 251 | } 252 | 253 | n = i; 254 | qsort(arg,n,sizeof(const char *),mycompare); 255 | 256 | i = 0; 257 | while(i < n) 258 | { 259 | bzero(data,MAXSZ); 260 | lstat(*(arg + i),&file_buff); 261 | gp = getgrgid(file_buff.st_gid); 262 | pw = getpwuid(file_buff.st_uid); 263 | info = localtime(&(file_buff.st_mtime)); 264 | strftime(time_buff,sizeof(time_buff),"%b %d %H:%M",info); 265 | 266 | /* Selecting file type */ 267 | switch(file_buff.st_mode & S_IFMT) 268 | { 269 | case S_IFCHR: 270 | sprintf(data,"c"); 271 | break; 272 | case S_IFBLK: 273 | sprintf(data,"b"); 274 | break; 275 | case S_IFDIR: 276 | sprintf(data,"d"); 277 | break; 278 | case S_IFLNK: 279 | sprintf(data,"l"); 280 | break; 281 | case S_IFIFO: 282 | sprintf(data,"p"); 283 | break; 284 | case S_IFSOCK: 285 | sprintf(data,"s"); 286 | break; 287 | default: 288 | sprintf(data,"-"); 289 | break; 290 | } 291 | 292 | 293 | /* File permissions */ 294 | if(file_buff.st_mode & S_IRUSR) 295 | strcat(data,"r"); 296 | else 297 | strcat(data,"-"); 298 | 299 | if(file_buff.st_mode & S_IWUSR) 300 | strcat(data,"w"); 301 | else 302 | strcat(data,"-"); 303 | 304 | if(file_buff.st_mode & S_IXUSR) 305 | strcat(data,"x"); 306 | else 307 | strcat(data,"-"); 308 | 309 | if(file_buff.st_mode & S_IRGRP) 310 | strcat(data,"r"); 311 | else 312 | strcat(data,"-"); 313 | 314 | if(file_buff.st_mode & S_IWGRP) 315 | strcat(data,"w"); 316 | else 317 | strcat(data,"-"); 318 | 319 | if(file_buff.st_mode & S_IXGRP) 320 | strcat(data,"x"); 321 | else 322 | strcat(data,"-"); 323 | 324 | if(file_buff.st_mode & S_IROTH) 325 | strcat(data,"r"); 326 | else 327 | strcat(data,"-"); 328 | 329 | if(file_buff.st_mode & S_IWOTH) 330 | strcat(data,"w"); 331 | else 332 | strcat(data,"-"); 333 | 334 | if(file_buff.st_mode & S_IXOTH) 335 | strcat(data,"x"); 336 | else 337 | strcat(data,"-"); 338 | 339 | // while(gtk_events_pending()) 340 | // gtk_main_iteration(); 341 | write(app_state->temp_file_descriptor_cli,data,strlen(data)); 342 | bzero(data,MAXSZ); 343 | if(((file_buff.st_mode & S_IFMT)^S_IFCHR) == 0 || ((file_buff.st_mode & S_IFMT)^S_IFBLK) ==0) 344 | sprintf(data," %d %s %s 0 %s %s\n",(int)file_buff.st_nlink,pw->pw_name,gp->gr_name,time_buff,*(arg + i)); 345 | else 346 | sprintf(data," %d %s %s %u %s %s\n",(int)file_buff.st_nlink,pw->pw_name,gp->gr_name,(unsigned int)file_buff.st_size,time_buff,*(arg + i)); 347 | 348 | write(app_state->temp_file_descriptor_cli,data,strlen(data)); 349 | 350 | i++; 351 | } 352 | 353 | closedir(fd); 354 | 355 | } 356 | 357 | -------------------------------------------------------------------------------- /GUI/list_content.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | List the contents of current working directory on server (`ls` and `ls -l` linux commands). 4 | */ 5 | void list_content(char *arg, char *user_input, Appstate *app_state) 6 | { 7 | /* Temporary variables */ 8 | int no_of_bytes; 9 | int port; 10 | int newsockfd; 11 | 12 | struct timeval tm;/* time structure to set time wait for receive buffer */ 13 | tm.tv_sec = 4; 14 | tm.tv_usec = 750000; 15 | 16 | char message_from_server[MAXSZ]; 17 | char message_to_server[MAXSZ]; 18 | 19 | /* Initialise character arrays */ 20 | bzero(message_from_server,MAXSZ); 21 | bzero(message_to_server,MAXSZ); 22 | bzero(buff,MAXSZ1); 23 | /* Request server to start BINARY mode */ 24 | send(app_state->sockfd,"TYPE I\r\n",8,0); 25 | 26 | sprintf(buff,"Command: TYPE I\nResponse: "); 27 | print_buff(app_state); 28 | 29 | 30 | while((no_of_bytes = recv(app_state->sockfd,message_from_server,MAXSZ,0)) > 0) 31 | { 32 | message_from_server[no_of_bytes] = '\0'; 33 | sprintf(buff,"%s",message_from_server); 34 | print_buff(app_state); 35 | 36 | if(strstr(message_from_server,"200 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"504 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 37 | break; 38 | } 39 | 40 | sprintf(buff,"\n"); 41 | print_buff(app_state); 42 | 43 | 44 | if(strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"504 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 45 | return; 46 | 47 | /* Request server to connect to PASSIVE port for file transfers */ 48 | send(app_state->sockfd,passive,strlen(passive),0); 49 | sprintf(buff,"Command: %sResponse: ",passive); 50 | print_buff(app_state); 51 | 52 | while((no_of_bytes = recv(app_state->sockfd,message_from_server,MAXSZ,0)) > 0) 53 | { 54 | message_from_server[no_of_bytes] = '\0'; 55 | sprintf(buff,"%s",message_from_server); 56 | print_buff(app_state); 57 | 58 | if(strstr(message_from_server,"227 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"502 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 59 | break; 60 | } 61 | sprintf(buff,"\n"); 62 | print_buff(app_state); 63 | 64 | if(strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"502 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 65 | return; 66 | 67 | /* Request acepted. Connect to PASSIVE port */ 68 | if(strncmp(message_from_server,"227",3)== 0) 69 | { 70 | 71 | /* Generate PORT address */ 72 | port = passive_port_number(message_from_server); 73 | 74 | /* Create socket for PASSIVE connection */ 75 | newsockfd = func_to_connect_passive(arg,port); 76 | 77 | if(strcmp(user_input,"ls -l") == 0) 78 | sprintf(message_to_server,"LIST -l\r\n");/* ls -l */ 79 | else 80 | sprintf(message_to_server,"NLST\r\n");/* ls */ 81 | 82 | sprintf(buff,"Command: %sResponse: ",message_to_server); 83 | print_buff(app_state); 84 | 85 | send(app_state->sockfd,message_to_server,strlen(message_to_server),0); 86 | 87 | 88 | while((no_of_bytes = recv(app_state->sockfd,message_from_server,MAXSZ,0)) > 0) 89 | { 90 | message_from_server[no_of_bytes] = '\0'; 91 | sprintf(buff,"%s",message_from_server); 92 | print_buff(app_state); 93 | 94 | 95 | if(strstr(message_from_server,"550 ") > 0||strstr(message_from_server,"425 ") > 0|| strstr(message_from_server,"125 ") > 0||strstr(message_from_server,"150 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"502 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 96 | break; 97 | } 98 | sprintf(buff,"\n"); 99 | print_buff(app_state); 100 | 101 | 102 | if(strncmp(message_from_server,"125",3) != 0 && strncmp(message_from_server,"150",3) != 0) 103 | return; 104 | 105 | 106 | /* Read data on new PASSIVE socket */ 107 | bzero(buff,MAXSZ1); 108 | while((no_of_bytes = recv(newsockfd,message_from_server,MAXSZ,0)) > 0) 109 | { 110 | message_from_server[no_of_bytes] = '\0'; 111 | sprintf(buff,"%s",message_from_server); 112 | print_buff(app_state); 113 | 114 | } 115 | sprintf(buff,"\n"); 116 | print_buff(app_state); 117 | 118 | 119 | close(newsockfd);/* Close PASSIVE connection */ 120 | 121 | /* Set time boundation on receive buffer */ 122 | setsockopt(app_state->sockfd, SOL_SOCKET, SO_RCVTIMEO,(char *)&tm,sizeof(tm)); 123 | while((no_of_bytes = recv(app_state->sockfd,message_from_server,MAXSZ,0)) > 0) 124 | { 125 | message_from_server[no_of_bytes] = '\0'; 126 | sprintf(buff,"%s",message_from_server); 127 | print_buff(app_state); 128 | if(strstr(message_from_server,"226 ") > 0) 129 | break; 130 | } 131 | sprintf(buff,"\n"); 132 | print_buff(app_state); 133 | 134 | bzero(buff,MAXSZ1); 135 | 136 | tm.tv_sec = 0; 137 | tm.tv_usec = 0; 138 | setsockopt(app_state->sockfd, SOL_SOCKET, SO_RCVTIMEO,(char *)&tm,sizeof(tm)); 139 | } 140 | 141 | } 142 | 143 | -------------------------------------------------------------------------------- /GUI/list_content_view.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Write the contents of current working directory on server to temporary file 4 | */ 5 | int list_content_view(char *arg, char *user_input, Appstate *app_state) 6 | { 7 | /* Temporary variables */ 8 | int no_of_bytes; 9 | int port; 10 | int newsockfd; 11 | int p; 12 | int total; 13 | 14 | struct timeval tm;/* time structure to set time wait for receive buffer */ 15 | tm.tv_sec = 4; 16 | tm.tv_usec = 750000; 17 | 18 | char message_from_server[MAXSZ]; 19 | char message_to_server[MAXSZ]; 20 | 21 | /* Initialise character arrays */ 22 | bzero(message_from_server,MAXSZ); 23 | bzero(message_to_server,MAXSZ); 24 | /* Request server to start BINARY mode */ 25 | send(app_state->sockfd,"TYPE I\r\n",8,0); 26 | 27 | // while(gtk_events_pending()) 28 | // gtk_main_iteration(); 29 | 30 | 31 | while((no_of_bytes = recv(app_state->sockfd,message_from_server,MAXSZ,0)) > 0) 32 | { 33 | message_from_server[no_of_bytes] = '\0'; 34 | // while(gtk_events_pending()) 35 | // gtk_main_iteration(); 36 | 37 | if(strstr(message_from_server,"200 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"504 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 38 | break; 39 | } 40 | 41 | 42 | if(strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"504 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 43 | return -1; 44 | 45 | /* Request server to connect to PASSIVE port for file transfers */ 46 | send(app_state->sockfd,passive,strlen(passive),0); 47 | 48 | while((no_of_bytes = recv(app_state->sockfd,message_from_server,MAXSZ,0)) > 0) 49 | { 50 | message_from_server[no_of_bytes] = '\0'; 51 | // while(gtk_events_pending()) 52 | // gtk_main_iteration(); 53 | 54 | if(strstr(message_from_server,"227 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"502 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 55 | break; 56 | } 57 | 58 | if(strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"502 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 59 | return -1; 60 | 61 | /* Request acepted. Connect to PASSIVE port */ 62 | if(strncmp(message_from_server,"227",3)== 0) 63 | { 64 | 65 | /* Generate PORT address */ 66 | port = passive_port_number(message_from_server); 67 | 68 | /* Create socket for PASSIVE connection */ 69 | newsockfd = func_to_connect_passive(arg,port); 70 | 71 | if(strcmp(user_input,"ls -l") == 0) 72 | sprintf(message_to_server,"LIST -l\r\n");/* ls -l */ 73 | else 74 | sprintf(message_to_server,"NLST\r\n");/* ls */ 75 | 76 | 77 | send(app_state->sockfd,message_to_server,strlen(message_to_server),0); 78 | 79 | 80 | while((no_of_bytes = recv(app_state->sockfd,message_from_server,MAXSZ,0)) > 0) 81 | { 82 | message_from_server[no_of_bytes] = '\0'; 83 | // while(gtk_events_pending()) 84 | // gtk_main_iteration(); 85 | 86 | if(strstr(message_from_server,"550 ") > 0 || strstr(message_from_server,"425 ") > 0|| strstr(message_from_server,"125 ") > 0||strstr(message_from_server,"150 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"502 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 87 | break; 88 | } 89 | 90 | 91 | if(strncmp(message_from_server,"125",3) != 0 && strncmp(message_from_server,"150",3) != 0) 92 | { 93 | close(newsockfd); 94 | return -1; 95 | } 96 | 97 | /* Read data on new PASSIVE socket */ 98 | while((no_of_bytes = recv(newsockfd,message_from_server,MAXSZ,0)) > 0) 99 | { 100 | message_from_server[no_of_bytes] = '\0'; 101 | /* Write to temporary file */ 102 | total = 0; 103 | while(total < no_of_bytes) 104 | { 105 | p = write(app_state->temp_file_descriptor,message_from_server + total,no_of_bytes - total); 106 | total += p; 107 | // while(gtk_events_pending()) 108 | // gtk_main_iteration(); 109 | } 110 | } 111 | 112 | close(newsockfd);/* Close PASSIVE connection */ 113 | 114 | /* Set time boundation on receive buffer */ 115 | setsockopt(app_state->sockfd, SOL_SOCKET, SO_RCVTIMEO,(char *)&tm,sizeof(tm)); 116 | while((no_of_bytes = recv(app_state->sockfd,message_from_server,MAXSZ,0)) > 0) 117 | { 118 | message_from_server[no_of_bytes] = '\0'; 119 | // while(gtk_events_pending()) 120 | // gtk_main_iteration(); 121 | if(strstr(message_from_server,"226 ") > 0) 122 | break; 123 | } 124 | 125 | 126 | tm.tv_sec = 0; 127 | tm.tv_usec = 0; 128 | setsockopt(app_state->sockfd, SOL_SOCKET, SO_RCVTIMEO,(char *)&tm,sizeof(tm)); 129 | 130 | } 131 | return 0; 132 | 133 | } 134 | 135 | 136 | -------------------------------------------------------------------------------- /GUI/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohit-takhar/Multithreaded-ftp-client-in-C/7bd675534d2fbaa1ff36c60fc225a1e91d7d1498/GUI/logo.png -------------------------------------------------------------------------------- /GUI/passive_connect.h: -------------------------------------------------------------------------------- 1 | /* 2 | Generate a passive PORT number from the variables sent by server. 3 | */ 4 | int passive_port_number(char *message) 5 | { 6 | int i = INITIALISE; 7 | int count = INITIALISE; 8 | int port = INITIALISE; 9 | char *token; 10 | char delim[]=" ,)";/* Delimiters for strtok()*/ 11 | 12 | while(message[i] != '\0' && count < 4)/* To reach to th first PORT variable */ 13 | { 14 | if(message[i] == ',') 15 | { 16 | count++; 17 | } 18 | i++; 19 | } 20 | 21 | count = 0; 22 | 23 | token = strtok(message + i,delim); 24 | while(token != NULL) 25 | { 26 | if(isdigit(token[0])) 27 | { 28 | if(count == 1) 29 | { 30 | port += atoi(token); 31 | } 32 | 33 | if(count == 0) 34 | { 35 | port = atoi(token)*256; 36 | count++; 37 | } 38 | 39 | } 40 | token = strtok(NULL,delim); 41 | } 42 | return port; 43 | 44 | } 45 | 46 | /* Create PASSIVE socket and connect to server */ 47 | int func_to_connect_passive(char *address,int port) 48 | { 49 | int newsockfd; 50 | struct sockaddr_in new_serverAddress; 51 | 52 | newsockfd = socket(AF_INET,SOCK_STREAM,0); 53 | bzero(&new_serverAddress,sizeof(new_serverAddress)); 54 | 55 | new_serverAddress.sin_family = AF_INET; 56 | new_serverAddress.sin_addr.s_addr = inet_addr(address); 57 | new_serverAddress.sin_port = htons(port); 58 | 59 | connect(newsockfd,(struct sockaddr *)&new_serverAddress,sizeof(new_serverAddress)); 60 | 61 | return newsockfd; 62 | } 63 | -------------------------------------------------------------------------------- /GUI/print_buff.h: -------------------------------------------------------------------------------- 1 | /* 2 | Print buffer on text view 3 | */ 4 | void print_buff(Appstate *app_state) 5 | { 6 | GtkTextIter iter; 7 | GtkTextMark *mark; 8 | 9 | buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(app_state->text_view)); 10 | mark = gtk_text_buffer_get_insert(buffer); 11 | gtk_text_buffer_get_iter_at_mark(buffer,&iter,mark); 12 | gdk_threads_enter(); 13 | gtk_text_buffer_insert(buffer,&iter,buff,strlen(buff)); 14 | 15 | gtk_text_buffer_get_end_iter(buffer,&iter); 16 | gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(app_state->text_view),&iter,0.0,FALSE,0,0); 17 | gdk_threads_leave(); 18 | 19 | bzero(buff,MAXSZ); 20 | 21 | } 22 | 23 | -------------------------------------------------------------------------------- /GUI/print_buff1.h: -------------------------------------------------------------------------------- 1 | /* 2 | Print buffer on text view 3 | */ 4 | void print_buff1(Appstate *app_state) 5 | { 6 | GtkTextIter iter; 7 | GtkTextMark *mark; 8 | 9 | buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(app_state->text_view)); 10 | mark = gtk_text_buffer_get_insert(buffer); 11 | gtk_text_buffer_get_iter_at_mark(buffer,&iter,mark); 12 | gtk_text_buffer_insert(buffer,&iter,buff,strlen(buff)); 13 | 14 | gtk_text_buffer_get_end_iter(buffer,&iter); 15 | gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(app_state->text_view),&iter,0.0,FALSE,0,0); 16 | 17 | bzero(buff,MAXSZ); 18 | 19 | } 20 | 21 | -------------------------------------------------------------------------------- /GUI/put_content.h: -------------------------------------------------------------------------------- 1 | /* 2 | Upload files on server. 3 | */ 4 | void put_content(char *arg,char *user_input,Appstate *app_state) 5 | { 6 | /* Temporary variables*/ 7 | int no_of_bytes; 8 | int port; 9 | int newsockfd; 10 | int fd; 11 | int p; 12 | int total; 13 | int temp; 14 | int temp1; 15 | int file_size; 16 | int size; 17 | int down = 2; 18 | 19 | clock_t start,end; 20 | double cpu_time; 21 | 22 | struct timeval tm;/* time structure to set time wait for receive buffer */ 23 | struct stat file_buff; 24 | 25 | tm.tv_sec = 1; 26 | tm.tv_usec = 750000; 27 | 28 | char message_from_server[MAXSZ]; 29 | char message_to_server[MAXSZ]; 30 | char file[MAXSZ];// File name 31 | char file_name[MAXSZ];// File name with instruction to server 32 | char data[MAXSZ];// Data transfer 33 | 34 | /* Initialise all the character arrays */ 35 | bzero(message_from_server,MAXSZ); 36 | bzero(message_to_server,MAXSZ); 37 | bzero(file_name,MAXSZ); 38 | bzero(file,MAXSZ); 39 | bzero(data,MAXSZ); 40 | 41 | /* Tell server to change to BINARY mode */ 42 | send(app_state->sockfd,"TYPE I\r\n",8,0); 43 | sprintf(buff,"Command: TYPE I\nResponse: "); 44 | print_buff(app_state); 45 | 46 | while((no_of_bytes = recv(app_state->sockfd,message_from_server,MAXSZ,0)) > 0) 47 | { 48 | message_from_server[no_of_bytes] = '\0'; 49 | sprintf(buff,"%s",message_from_server); 50 | print_buff(app_state); 51 | 52 | if(strstr(message_from_server,"200 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"504 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 53 | break; 54 | } 55 | sprintf(buff,"\n"); 56 | print_buff(app_state); 57 | 58 | if(strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"504 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 59 | return; 60 | 61 | /* Send request for PASSIVE connection */ 62 | send(app_state->sockfd,passive,strlen(passive),0); 63 | sprintf(buff,"Command: %sResponse: ",passive); 64 | print_buff(app_state); 65 | 66 | while((no_of_bytes = recv(app_state->sockfd,message_from_server,MAXSZ,0)) > 0) 67 | { 68 | message_from_server[no_of_bytes] = '\0'; 69 | sprintf(buff,"%s",message_from_server); 70 | 71 | print_buff(app_state); 72 | 73 | if(strstr(message_from_server,"227 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"502 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 74 | break; 75 | 76 | } 77 | sprintf(buff,"\n"); 78 | print_buff(app_state); 79 | 80 | if(strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"502 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 81 | return; 82 | 83 | /* Server accepts request and sends PORT variables */ 84 | if(strncmp(message_from_server,"227",3) == 0) 85 | { 86 | /* Generate a PORT number using PORT variables */ 87 | port = passive_port_number(message_from_server); 88 | 89 | /* Connect to server using another PORT for file transfers */ 90 | newsockfd = func_to_connect_passive(arg,port); 91 | 92 | /* Send file name to server */ 93 | sprintf(file_name,"STOR %s\r\n",user_input + 4); 94 | sprintf(buff,"Command: STOR %s\nResponse: ",user_input + 4); 95 | 96 | print_buff(app_state); 97 | send(app_state->sockfd,file_name,strlen(file_name),0); 98 | 99 | while((no_of_bytes = recv(app_state->sockfd,message_from_server,MAXSZ,0)) > 0) 100 | { 101 | message_from_server[no_of_bytes] = '\0'; 102 | sprintf(buff,"%s",message_from_server); 103 | print_buff(app_state); 104 | 105 | if(strstr(message_from_server,"450 ") > 0 ||strstr(message_from_server,"550 ") > 0 ||strstr(message_from_server,"125 ") > 0 ||strstr(message_from_server,"150 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"452 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0 || strstr(message_from_server,"553 ") > 0 ||strstr(message_from_server,"532 ") > 0) 106 | break; 107 | } 108 | sprintf(buff,"\n"); 109 | print_buff(app_state); 110 | 111 | /* Send file data to server */ 112 | if(strncmp(message_from_server,"150",3) == 0 || strncmp(message_from_server,"125",3) == 0) 113 | { 114 | sprintf(file,"%s",user_input + 4); 115 | 116 | fd = open(file,O_RDONLY); 117 | fstat(fd,&file_buff); 118 | size = (int)file_buff.st_size; 119 | file_size = 0; 120 | if(size % 100 == 0) 121 | temp = (size / 100); 122 | else 123 | temp = (size / 100) + 1; 124 | 125 | temp1 = temp; 126 | sprintf(buff,"Uploading ["); 127 | print_buff(app_state); 128 | 129 | start = clock(); 130 | 131 | while(size > 0) 132 | { 133 | no_of_bytes = read(fd,data,MAXSZ); 134 | file_size += no_of_bytes; 135 | temp1 = temp * down; 136 | 137 | while(temp1 <= file_size) 138 | { 139 | sprintf(buff,"#"); 140 | print_buff(app_state); 141 | down += 2; 142 | temp1 = temp * down; 143 | } 144 | total = 0; 145 | while(total < no_of_bytes) 146 | { 147 | p = send(newsockfd,data + total,no_of_bytes - total,0); 148 | total += p; 149 | } 150 | size -= no_of_bytes; 151 | bzero(data,MAXSZ); 152 | } 153 | 154 | end = clock(); 155 | 156 | sprintf(buff,"] 100%%\n"); 157 | print_buff(app_state); 158 | 159 | cpu_time = ((double)(end - start))/CLOCKS_PER_SEC; 160 | sprintf(buff,"Time taken %lf\n\n",cpu_time); 161 | print_buff(app_state); 162 | 163 | close(fd); 164 | close(newsockfd); 165 | /* Set time boundation on receive buffer */ 166 | setsockopt(app_state->sockfd, SOL_SOCKET, SO_RCVTIMEO,(char *)&tm,sizeof(tm)); 167 | while((no_of_bytes = recv(app_state->sockfd,message_from_server,MAXSZ,0)) > 0) 168 | { 169 | message_from_server[no_of_bytes] = '\0'; 170 | sprintf(buff,"%s",message_from_server); 171 | print_buff(app_state); 172 | if(strstr(message_from_server,"226 ") > 0) 173 | break; 174 | } 175 | sprintf(buff,"\n"); 176 | print_buff(app_state); 177 | } 178 | 179 | } 180 | } 181 | 182 | -------------------------------------------------------------------------------- /GUI/put_unique.h: -------------------------------------------------------------------------------- 1 | /* 2 | Upload files on server. 3 | */ 4 | void *put_unique(void *thread_data) 5 | { 6 | 7 | struct data *my_data; 8 | my_data = (struct data *)thread_data; 9 | 10 | char *arg = my_data->argv1; 11 | char *user_input = my_data->user_data; 12 | Appstate *app_state = my_data->app_state; 13 | 14 | /* Temporary variables*/ 15 | int no_of_bytes; 16 | int port; 17 | int newsockfd; 18 | int fd; 19 | int p; 20 | int total; 21 | int temp; 22 | int temp1; 23 | int file_size; 24 | int size; 25 | int down = 2; 26 | 27 | clock_t start; 28 | clock_t end; 29 | double cpu_time; 30 | start = clock();//Start clock 31 | 32 | struct timeval tm;/* time structure to set time wait for receive buffer */ 33 | struct stat file_buff; 34 | 35 | tm.tv_sec = 1; 36 | tm.tv_usec = 750000; 37 | 38 | char message_from_server[MAXSZ]; 39 | char message_to_server[MAXSZ]; 40 | char file[MAXSZ];// File name 41 | char file_name[MAXSZ];// File name with instruction to server 42 | char data[MAXSZ];// Data transfer 43 | 44 | /* Initialise all the character arrays */ 45 | bzero(message_from_server,MAXSZ); 46 | bzero(message_to_server,MAXSZ); 47 | bzero(file_name,MAXSZ); 48 | bzero(file,MAXSZ); 49 | bzero(data,MAXSZ); 50 | 51 | /* Tell server to change to BINARY mode */ 52 | send(app_state->sockfd,"TYPE I\r\n",8,0); 53 | sprintf(buff,"Command: TYPE I\nResponse: "); 54 | print_buff(app_state); 55 | 56 | while((no_of_bytes = recv(app_state->sockfd,message_from_server,MAXSZ,0)) > 0) 57 | { 58 | message_from_server[no_of_bytes] = '\0'; 59 | sprintf(buff,"%s",message_from_server); 60 | print_buff(app_state); 61 | 62 | if(strstr(message_from_server,"200 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"504 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 63 | break; 64 | } 65 | sprintf(buff,"\n"); 66 | print_buff(app_state); 67 | 68 | if(strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"504 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 69 | { 70 | global_val = 1; 71 | // return; 72 | pthread_exit(NULL); 73 | } 74 | 75 | /* Send request for PASSIVE connection */ 76 | send(app_state->sockfd,passive,strlen(passive),0); 77 | sprintf(buff,"Command: %sResponse: ",passive); 78 | print_buff(app_state); 79 | 80 | while((no_of_bytes = recv(app_state->sockfd,message_from_server,MAXSZ,0)) > 0) 81 | { 82 | message_from_server[no_of_bytes] = '\0'; 83 | sprintf(buff,"%s",message_from_server); 84 | 85 | print_buff(app_state); 86 | 87 | if(strstr(message_from_server,"227 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"502 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 88 | break; 89 | 90 | } 91 | sprintf(buff,"\n"); 92 | print_buff(app_state); 93 | 94 | if(strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"502 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 95 | { 96 | global_val = 1; 97 | pthread_exit(NULL); 98 | //return; 99 | } 100 | 101 | /* Server accepts request and sends PORT variables */ 102 | if(strncmp(message_from_server,"227",3) == 0) 103 | { 104 | /* Generate a PORT number using PORT variables */ 105 | port = passive_port_number(message_from_server); 106 | 107 | /* Connect to server using another PORT for file transfers */ 108 | newsockfd = func_to_connect_passive(arg,port); 109 | 110 | /* Send file name to server */ 111 | sprintf(file_name,"STOU %s\r\n",user_input + 8); 112 | sprintf(buff,"Command: STOU %s\nResponse: ",user_input + 8); 113 | 114 | print_buff(app_state); 115 | send(app_state->sockfd,file_name,strlen(file_name),0); 116 | 117 | while((no_of_bytes = recv(app_state->sockfd,message_from_server,MAXSZ,0)) > 0) 118 | { 119 | message_from_server[no_of_bytes] = '\0'; 120 | sprintf(buff,"%s",message_from_server); 121 | print_buff(app_state); 122 | 123 | if(strstr(message_from_server,"450 ") > 0 ||strstr(message_from_server,"550 ") > 0 ||strstr(message_from_server,"125 ") > 0 ||strstr(message_from_server,"150 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"452 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0 || strstr(message_from_server,"553 ") > 0 ||strstr(message_from_server,"532 ") > 0) 124 | break; 125 | } 126 | sprintf(buff,"\n"); 127 | print_buff(app_state); 128 | 129 | /* Send file data to server */ 130 | if(strncmp(message_from_server,"150",3) == 0 || strncmp(message_from_server,"125",3) == 0) 131 | { 132 | sprintf(file,"%s",user_input + 8); 133 | 134 | fd = open(file,O_RDONLY); 135 | fstat(fd,&file_buff); 136 | size = (int)file_buff.st_size; 137 | file_size = 0; 138 | if(size % 100 == 0) 139 | temp = (size / 100); 140 | else 141 | temp = (size / 100) + 1; 142 | 143 | temp1 = temp; 144 | sprintf(buff,"Uploading ["); 145 | print_buff(app_state); 146 | 147 | 148 | while(size > 0) 149 | { 150 | no_of_bytes = read(fd,data,MAXSZ); 151 | file_size += no_of_bytes; 152 | temp1 = temp * down; 153 | 154 | while(temp1 <= file_size) 155 | { 156 | sprintf(buff,"#"); 157 | print_buff(app_state); 158 | down += 2; 159 | temp1 = temp * down; 160 | } 161 | total = 0; 162 | while(total < no_of_bytes) 163 | { 164 | p = send(newsockfd,data + total,no_of_bytes - total,0); 165 | total += p; 166 | } 167 | size -= no_of_bytes; 168 | bzero(data,MAXSZ); 169 | } 170 | 171 | 172 | sprintf(buff,"] 100%%\n"); 173 | print_buff(app_state); 174 | 175 | 176 | close(fd); 177 | close(newsockfd); 178 | /* Set time boundation on receive buffer */ 179 | setsockopt(app_state->sockfd, SOL_SOCKET, SO_RCVTIMEO,(char *)&tm,sizeof(tm)); 180 | while((no_of_bytes = recv(app_state->sockfd,message_from_server,MAXSZ,0)) > 0) 181 | { 182 | message_from_server[no_of_bytes] = '\0'; 183 | sprintf(buff,"%s",message_from_server); 184 | print_buff(app_state); 185 | if(strstr(message_from_server,"226 ") > 0) 186 | break; 187 | } 188 | sprintf(buff,"\n"); 189 | print_buff(app_state); 190 | 191 | end = clock();//Stop clock 192 | cpu_time = ((double)(end - start))/CLOCKS_PER_SEC;//Calculate CPU time 193 | sprintf(buff,"Time taken %lf\n\n",cpu_time); 194 | print_buff(app_state); 195 | } 196 | global_val = 1; 197 | } 198 | pthread_exit(NULL); 199 | // return; 200 | } 201 | 202 | -------------------------------------------------------------------------------- /GUI/thread_get.h: -------------------------------------------------------------------------------- 1 | /* 2 | Each thread will establish an instruction connection and a passive connection to server. 3 | */ 4 | void *function(void *point) 5 | { 6 | int sockfd; 7 | int temp = 0; 8 | int no_of_bytes; 9 | int newsockfd; 10 | int fd; 11 | int port; 12 | int total; 13 | int p; 14 | int size; 15 | int temp_size; 16 | 17 | struct sockaddr_in serverAddress; 18 | 19 | struct userdetails *obj; 20 | obj = (struct userdetails *)point; 21 | 22 | char message_from_server[MAXSZ]; 23 | char message_to_server[MAXSZ]; 24 | char data[MAXSZ]; 25 | char file[MAXSZ];// File name 26 | char file_name[MAXSZ];// File name with instruction to server 27 | 28 | 29 | /* Initialise all the character arrays */ 30 | bzero(message_from_server,MAXSZ); 31 | bzero(message_to_server,MAXSZ); 32 | bzero(file_name,MAXSZ); 33 | bzero(file,MAXSZ); 34 | bzero(data,MAXSZ); 35 | 36 | sockfd = socket(AF_INET,SOCK_STREAM,0); 37 | 38 | bzero(&serverAddress,sizeof(serverAddress));/* Initialise structure */ 39 | 40 | serverAddress.sin_family = AF_INET; 41 | serverAddress.sin_addr.s_addr = inet_addr(obj->arg); 42 | serverAddress.sin_port = htons(PORT); 43 | 44 | /* Connect to server */ 45 | connect(sockfd,(struct sockaddr *)&serverAddress,sizeof(serverAddress)); 46 | /* if(connect_value == -1)// Connection Error 47 | { 48 | perror("Error"); 49 | exit(1); 50 | } 51 | 52 | */ 53 | /* Receive message from server "Server will send 220" */ 54 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0 ) 55 | { 56 | message_from_server[no_of_bytes] = '\0'; 57 | 58 | if(strstr(message_from_server,"220 ") > 0 || strstr(message_from_server,"421 ") > 0) 59 | break; 60 | } 61 | 62 | send(sockfd,user,strlen(user),0);/* Send username to server */ 63 | 64 | 65 | /* 66 | Receive message from server after sending user name. 67 | Message with code 331 asks you to enter password corresponding to user. 68 | Message with code 230 means no password is required for the entered username(LOGIN successful). 69 | */ 70 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 71 | { 72 | message_from_server[no_of_bytes] = '\0'; 73 | if(strncmp(message_from_server,"331",3) == 0) 74 | { 75 | temp = 1; 76 | } 77 | 78 | if(strncmp(message_from_server,"230",3) == 0) 79 | { 80 | temp = 2; 81 | } 82 | 83 | if(strncmp(message_from_server,"530",3) == 0) 84 | { 85 | temp = 0; 86 | } 87 | if(strstr(message_from_server,"230 ") > 0 || strstr(message_from_server,"500 ") > 0 || strstr(message_from_server,"501 ") > 0 || strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"332 ") > 0 || strstr(message_from_server,"530 ")|| strstr(message_from_server,"331 ") > 0) 88 | break; 89 | } 90 | 91 | if(temp == 1)//Password is required for server 92 | { 93 | send(sockfd,pass,strlen(pass),0);/* Send password to server */ 94 | 95 | /* Receive message from server */ 96 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 97 | { 98 | message_from_server[no_of_bytes] = '\0'; 99 | 100 | if(strstr(message_from_server,"230 ") > 0 || strstr(message_from_server,"500 ") > 0 || strstr(message_from_server,"501 ") > 0 || strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"332 ") > 0 || strstr(message_from_server,"530 ")|| strstr(message_from_server,"503 ") > 0 || strstr(message_from_server,"202 ") > 0) 101 | break; 102 | 103 | } 104 | } 105 | 106 | 107 | /* Tell server to change to BINARY mode */ 108 | send(sockfd,"TYPE I\r\n",8,0); 109 | 110 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 111 | { 112 | message_from_server[no_of_bytes] = '\0'; 113 | 114 | if(strstr(message_from_server,"200 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"504 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 115 | break; 116 | } 117 | 118 | 119 | /* Send request for PASSIVE connection */ 120 | send(sockfd,passive,strlen(passive),0); 121 | 122 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 123 | { 124 | message_from_server[no_of_bytes] = '\0'; 125 | if(strstr(message_from_server,"227 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"502 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 126 | break; 127 | } 128 | 129 | /* Server accepts request and sends PORT variables */ 130 | if(strncmp(message_from_server,"227",3) == 0) 131 | { 132 | /* Generate a PORT number using PORT variables */ 133 | port = passive_port_number(message_from_server); 134 | 135 | /* Connect to server using another PORT for file transfers */ 136 | newsockfd = func_to_connect_passive(obj->arg,port); 137 | 138 | sprintf(message_to_server,"REST %d\r\n",(obj->t_id)*(obj->size));//Starting byte of chunk of data that is required 139 | 140 | send(sockfd,message_to_server,strlen(message_to_server),0); 141 | 142 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 143 | { 144 | message_from_server[no_of_bytes] = '\0'; 145 | if(strstr(message_from_server,"350 ") > 0 || strstr(message_from_server,"500 ") > 0 || strstr(message_from_server,"501 ") > 0 || strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"502 ") > 0 || strstr(message_from_server,"530 ")) 146 | break; 147 | } 148 | 149 | sprintf(file,"%s%d",(obj->user_input) + 4,(obj->t_id)); 150 | 151 | /* Send file name */ 152 | sprintf(file_name,"RETR %s/%s\r\n",obj->pwd,(obj->user_input) + 4); 153 | send(sockfd,file_name,strlen(file_name),0); 154 | 155 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 156 | { 157 | message_from_server[no_of_bytes] = '\0'; 158 | if(strstr(message_from_server,"425 ") > 0|| strstr(message_from_server,"125 ") > 0 ||strstr(message_from_server,"150 ") > 0 || strstr(message_from_server,"501 ") > 0 ||strstr(message_from_server,"500 ") > 0 ||strstr(message_from_server,"550 ") > 0 ||strstr(message_from_server,"421 ") > 0 || strstr(message_from_server,"530 ") > 0) 159 | break; 160 | } 161 | 162 | int retry = 0; 163 | /* Create file on client system */ 164 | fd = open(file,O_CREAT|O_WRONLY|O_TRUNC,0644); 165 | size = 0; 166 | while((no_of_bytes = recv(newsockfd,data,MAXSZ,0)) > 0)//Get specific chunk of data 167 | { 168 | 169 | 170 | if(size >= obj->size) 171 | break; 172 | if(no_of_bytes == 0) 173 | { 174 | if( retry < 3) 175 | { 176 | retry++; 177 | continue; 178 | } 179 | else 180 | { 181 | pthread_exit(NULL); 182 | } 183 | } 184 | size += no_of_bytes; 185 | if(size > obj->size) 186 | { 187 | temp_size = no_of_bytes - (size - obj->size); 188 | 189 | size -= no_of_bytes; 190 | size += temp_size; 191 | no_of_bytes = temp_size; 192 | } 193 | 194 | total = 0; 195 | /* For partial write operations */ 196 | while(total < no_of_bytes) 197 | { 198 | p = write(fd,data + total,no_of_bytes - total); 199 | total += p; 200 | } 201 | 202 | } 203 | 204 | 205 | /* Close PASSIVE socket and file */ 206 | close(newsockfd); 207 | close(fd); 208 | while((no_of_bytes = recv(sockfd,message_from_server,MAXSZ,0)) > 0) 209 | { 210 | message_from_server[no_of_bytes] = '\0'; 211 | if(strstr(message_from_server,"226 ") > 0 || strstr(message_from_server,"426 ") > 0) 212 | break; 213 | } 214 | 215 | } 216 | close(sockfd);//Close connection 217 | 218 | 219 | pthread_exit((void *)point); 220 | } 221 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Multisegmented FTP client program in C 2 | Apart from all functionalities of standard FTP, the important thing on which I have worked is to increase the downloading speed of very large files using multithreading(used `POSIX` threads). 3 | For very large files, multiple threads are created and each thread creates an `instruction connection` and `data connection` with the server. Each thread downloads a specific chunk of data and then all are combined together to get the file. 4 | #Note: 5 | Use only for very large files because creating and managing threads is also an overhead for CPU. Performance will degrade for smaller files. 6 | 7 | Following functions are included. For example: 8 | `ls` : To list files in current directory on server side. 9 | `ls -l` : Same as `ls`, with some more details. 10 | `pwd` : Current working directory on server side. 11 | `get filename` : Download file from server.(File should be present on server side). 12 | `put filename` : Upload file on server. 13 | `uniqput filename` : Uniquely upload file on server. 14 | `mkdir directory_name` : Create directory on server. 15 | `rmdir directory_name` : Remove directory on server. 16 | `rm filename` : Remove file on server. 17 | `cd directory_name` : Traverse file system on server side. 18 | `rename old_filename new_filename` : Renaming file on server. 19 | 20 | `!ls` : To list files in current directory on client side. 21 | `!ls -l` : Same as `!ls`, with some more details. 22 | `!pwd` : Current working directory on client side. 23 | `!cd directory_name` : Traverse file system on client side. 24 | `!mkdir directory_name` : Create directory on client side. 25 | `!rmdir directory_name` : Remove directory on client side. 26 | 27 | To run: 28 | Run command `make all` to compile program. 29 | To execute, run `./myftp server-ip-address`. 30 | Enter user credentials to login on server. 31 | #Features in GUI(Apart from all the functionalities) 32 | * Drag N Drop to upload and download files. 33 | * Double click to enter directory. 34 | 35 | #Acknowledgements 36 | * Professor `Khushil Saini`, for the project idea and concepts about multithreading. 37 | * Stackoverflow community(http://stackoverflow.com). 38 | * The very helpful documentation of FTP `RFC 959`(https://www.ietf.org/rfc/rfc959.txt). 39 | 40 | #TODO List 41 | * Multiple selection 42 | * Progress Bar 43 | --------------------------------------------------------------------------------