├── project1_cse589.pdf ├── README.md ├── TCPSocketConnection.h └── DistributedFileTransfer.cpp /project1_cse589.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/router/rtorrent/master/project1_cse589.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | rtorrent 2 | ======== 3 | 4 | Exectution Parameters: 5 | `` `` `` 6 | 7 | A bit-torrent style distributed file transfer client. A file requested at any client is fetched chunk-wise from all connected clients over TCP connections. 8 | 9 | USAGE: 10 | 11 | HELP : Open this page 12 | 13 | MYIP :Display the IP address of this host. 14 | 15 | MYPORT : Display the port on which this process is listening for incoming connections. 16 | 17 | REGISTER `` ``: Used to register with the server and to get the IP and listening port numbers of all the peers currently registered with the server. 18 | 19 | SIP : Displays details of the other hosts that you can connect to. 20 | 21 | CONNECT `` ``: Establishes a new TCP connection to the 22 | specified `` at the specified ``. 23 | 24 | LIST: Display a numbered list of all the connections this process is part of. 25 | 26 | TERMINATE `` This command will terminate the connection listed under the specified number when LIST is used to display all connections. 27 | 28 | EXIT Close all connections and terminate this process. 29 | 30 | DOWNLOAD `` `` : The host shall download in parallel different chunks of file specified in the download command from all connected hosts until the complete file is downloaded. 31 | -------------------------------------------------------------------------------- /TCPSocketConnection.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TCPSocketConnection.h 3 | * 4 | * Created on: Sep 27, 2013 5 | * Author: subhranil 6 | */ 7 | 8 | 9 | /* An object of this class is created in the following two cases 10 | * 1) An incoming request on the listening port 11 | * 2)while connecting to another client 12 | * 13 | * 14 | */ 15 | 16 | #include 17 | #include "FileDetails.h" 18 | #ifndef TCPSOCKETCONNECTION_H_ 19 | #define TCPSOCKETCONNECTION_H_ 20 | 21 | class TCPSocketConnection { 22 | 23 | private: 24 | 25 | char sourceIP[32]; 26 | char destinationIP[32]; 27 | int sourcePort; 28 | int destinationPort; 29 | int socketId; 30 | char destinationHostName[1024]; 31 | bool connectionStatus; 32 | FileChunkDetails *chunkToBeTransferred; //ideally this should not be a member of this class. but this seems pretty tightly coupled. 33 | 34 | 35 | 36 | public: 37 | TCPSocketConnection(); 38 | TCPSocketConnection(char destIP[32],int destPort,int mode); 39 | TCPSocketConnection(struct sockaddr_in *peerAddressInfo,int connectionSocketId); 40 | int sendData(char *dataBuffer,int maxSendWindow=-1); 41 | char *getDestinationIP(); 42 | void setDestinationIP(char * str); 43 | int getDestinationPort(); 44 | void setDestinationPort(int port); 45 | int getSocketId(); 46 | char *getDestinationHostName(); 47 | void setDestinationHostName(char * str); 48 | void closeConnection(); 49 | void validateConnection(); 50 | bool isConnectionValid(); 51 | FileChunkDetails *assignedChunk(); 52 | void assignFileChunk(FileChunkDetails* det); 53 | virtual ~TCPSocketConnection(); 54 | }; 55 | 56 | #endif /* TCPSOCKETCONNECTION_H_ */ 57 | -------------------------------------------------------------------------------- /DistributedFileTransfer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * DistributedFileTransfer.cpp 3 | * 4 | * Created on: Sep 27, 2013 5 | * Author: subhranil 6 | */ 7 | 8 | 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include"TCPSocketConnection.h" 26 | 27 | #define MAXCLIENTS 10 // for the clients 28 | #define MAXConnections 100 // for the server 29 | #define MAXPACKETSIZE 10000 30 | 31 | 32 | #define SERVERIP "192.168.1.15" 33 | #define SERVERPORT 7788 34 | #define SERVERHOSTNAME "timberlake.cse.buffalo.edu" 35 | 36 | 37 | #define headerDelim "!@#$%^)(*&" 38 | #define PROMPTVAR "DistributedFileTransfer>>" 39 | 40 | long long int totalBytesTransferred=0; 41 | long long int totalTimeInMicroSecs=0; 42 | int totalBytesRecvd=0; 43 | 44 | 45 | typedef struct PeerDetails 46 | { 47 | char IP[40]; 48 | int port; 49 | char hostName[100]; 50 | } PeerDetails; 51 | 52 | 53 | #pragma mark Globals 54 | int localPort; 55 | bool isServer; 56 | char hostIP[32]; 57 | char localHostName[1024]; 58 | PeerDetails serverIPList[MAXConnections];//={"",0}; 59 | TCPSocketConnection* peerConnectionDetails[MAXCLIENTS]; 60 | FileChunkDetails* missedChunks[100]; 61 | int numberOfMissedChunks=0; 62 | int lastWrittenByte=0; 63 | bool downloadActive=false; 64 | 65 | int numberOfOpenConnections=0; 66 | typedef struct sockaddr_in SocketAddressInfo; 67 | 68 | // FileChunkDetails class definition 69 | 70 | FileChunkDetails::FileChunkDetails(char * filename,int sByte,int chunksize) 71 | { 72 | if(filename) 73 | strcpy(fileName,filename); 74 | startByte=sByte; 75 | chunkSize=chunksize; 76 | transferStatus=false; 77 | 78 | } 79 | char* FileChunkDetails::getFileName() 80 | { 81 | return fileName; 82 | } 83 | int FileChunkDetails::getStartByte() 84 | { 85 | return startByte; 86 | } 87 | int FileChunkDetails::getChunkSize() 88 | { 89 | return chunkSize; 90 | } 91 | void FileChunkDetails::setActiveTransfer() 92 | { 93 | transferStatus=true; 94 | } 95 | void FileChunkDetails::resetActiveTransfer() 96 | { 97 | transferStatus=false; 98 | } 99 | 100 | 101 | 102 | /***************************************************/ 103 | 104 | 105 | // TCP Socket Class definition 106 | TCPSocketConnection::TCPSocketConnection() { 107 | // TODO Auto-generated constructor stub 108 | 109 | 110 | } 111 | 112 | TCPSocketConnection::~TCPSocketConnection() { 113 | // TODO Auto-generated destructor stub 114 | if(chunkToBeTransferred) 115 | delete(chunkToBeTransferred); 116 | } 117 | 118 | 119 | TCPSocketConnection::TCPSocketConnection(char destIP[32],int destPort,int mode) 120 | { 121 | 122 | if(mode==0) // create a tcp socket 123 | { 124 | SocketAddressInfo *socketAddress; // this structure basically stores info about the socket address 125 | socketAddress=(SocketAddressInfo*)malloc(sizeof(SocketAddressInfo)); 126 | socketAddress->sin_family=AF_INET; 127 | 128 | socketAddress->sin_port=htons(destPort); 129 | inet_pton(socketAddress->sin_family,destIP,&(socketAddress->sin_addr)); 130 | 131 | //create a socket for connecting to server 132 | socketId=socket(AF_INET,SOCK_STREAM,0); 133 | if(socketId==-1) 134 | { 135 | printf("Error n creating socket"); 136 | return; 137 | } 138 | int retConnect=connect(socketId,(struct sockaddr*)socketAddress,sizeof(SocketAddressInfo)); 139 | if(retConnect<0) 140 | { 141 | connectionStatus=false; 142 | printf("Connection with peer failed"); 143 | return; 144 | } 145 | strcpy(destinationIP,destIP); 146 | destinationPort=destPort; 147 | getnameinfo((struct sockaddr*)socketAddress,sizeof(*socketAddress),destinationHostName,sizeof(destinationHostName),NULL,0,0); 148 | //getnameinfo((struct sockaddr*)&sa, sizeof(sa), node, sizeof(node), NULL, 0, 0); 149 | connectionStatus=true; 150 | } 151 | else // create an udp socket 152 | { 153 | SocketAddressInfo *socketAddress; // this structure basically stores info about the socket address 154 | socketAddress=(SocketAddressInfo*)malloc(sizeof(SocketAddressInfo)); 155 | socketAddress->sin_family=AF_INET; 156 | 157 | socketAddress->sin_port=htons(destPort); 158 | inet_pton(socketAddress->sin_family,destIP,&(socketAddress->sin_addr)); 159 | 160 | //create a socket for connecting to server 161 | socketId=socket(AF_INET,SOCK_DGRAM,0); 162 | if(socketId==-1) 163 | printf("Error n creating socket"); 164 | int retConnect=connect(socketId,(struct sockaddr*)socketAddress,sizeof(SocketAddressInfo)); 165 | if(retConnect<0) 166 | { 167 | connectionStatus=false; 168 | printf("connection with peer failed with error : %d",retConnect); 169 | } 170 | 171 | SocketAddressInfo localAddressInfo; 172 | socklen_t len=sizeof(localAddressInfo); 173 | getsockname(socketId,(struct sockaddr*)&localAddressInfo,&len); 174 | char buffer[32]; 175 | inet_ntop(AF_INET,&localAddressInfo.sin_addr,buffer,sizeof(buffer)); 176 | strcpy(hostIP,buffer); 177 | gethostname(localHostName,sizeof(localHostName)); 178 | } 179 | 180 | } 181 | 182 | // End of class declaration 183 | TCPSocketConnection::TCPSocketConnection(SocketAddressInfo* peerAddressInfo,int connectionSocketId) 184 | { 185 | 186 | 187 | //socklen_t len; 188 | //getsockname(connectionSocketId,peerAddressInfo,&len); 189 | //char buffer[32]; 190 | //strcpy(destinationIP,inet_ntoa(peerAddressInfo->sin_addr)); 191 | 192 | //inet_ntop(AF_INET,peerAddressInfo->sin_addr.s_addr,buffer,sizeof(buffer)); 193 | //strcpy(destinationIP,buffer); 194 | //destinationPort=peerAddressInfo->sin_port; 195 | socketId=connectionSocketId; 196 | connectionStatus=false; 197 | /*struct sockaddr peerInfo; 198 | 199 | socklen_t len=sizeof(peerInfo); 200 | getpeername(connectionSocketId,&peerInfo,&len); 201 | peerAddressInfo=(SocketAddressInfo*)&peerInfo; 202 | destinationPort=peerAddressInfo->sin_port;*/ 203 | 204 | 205 | //printf("incoming connection from %s-->%d\n",destinationIP,destinationPort); 206 | 207 | } 208 | void TCPSocketConnection::closeConnection() 209 | { 210 | close(socketId); 211 | } 212 | 213 | 214 | int TCPSocketConnection::sendData(char *dataBuffer,int maxSendWindow) 215 | { 216 | int retV=send(socketId,dataBuffer,(maxSendWindow==-1)?strlen(dataBuffer):maxSendWindow,0); 217 | //printf("sending:%s-->%d-->%d\n",dataBuffer,socketId,retV); 218 | return retV; 219 | } 220 | 221 | char *TCPSocketConnection::getDestinationIP() 222 | { 223 | return destinationIP; 224 | } 225 | int TCPSocketConnection::getDestinationPort() 226 | { 227 | return destinationPort; 228 | } 229 | 230 | int TCPSocketConnection::getSocketId() 231 | { 232 | return socketId; 233 | } 234 | 235 | char * TCPSocketConnection::getDestinationHostName() 236 | { 237 | return destinationHostName; 238 | } 239 | 240 | void TCPSocketConnection::setDestinationIP(char * str) 241 | { 242 | strcpy(destinationIP,str); 243 | } 244 | void TCPSocketConnection::setDestinationPort(int port) 245 | { 246 | destinationPort=port; 247 | } 248 | void TCPSocketConnection::setDestinationHostName(char * str) 249 | { 250 | strcpy(destinationHostName,str); 251 | } 252 | 253 | void TCPSocketConnection:: validateConnection() 254 | { 255 | 256 | connectionStatus=true; 257 | 258 | } 259 | bool TCPSocketConnection:: isConnectionValid() 260 | { 261 | return connectionStatus; 262 | } 263 | 264 | void TCPSocketConnection::assignFileChunk(FileChunkDetails* det) 265 | { 266 | if(chunkToBeTransferred) 267 | delete(chunkToBeTransferred); 268 | 269 | chunkToBeTransferred=det; 270 | } 271 | 272 | FileChunkDetails * TCPSocketConnection::assignedChunk() 273 | { 274 | return chunkToBeTransferred; 275 | } 276 | long long int getFileSize(char* fileName) 277 | { 278 | struct stat fileDetails; 279 | stat(fileName,&fileDetails); 280 | return fileDetails.st_size; 281 | } 282 | 283 | void getLocalIP() 284 | { 285 | TCPSocketConnection *udpConn=new TCPSocketConnection("8.8.8.8",53,1); 286 | udpConn->closeConnection(); 287 | delete(udpConn); 288 | } 289 | // host list handling mthds 290 | bool addConnection(TCPSocketConnection* newConn) 291 | { 292 | // add conn to the set of peer ids 293 | //printf("new connection"); 294 | bool isAdded=false; 295 | for(int i=0;icloseConnection(); 313 | free(peerConnectionDetails[id]); 314 | peerConnectionDetails[id]=0; 315 | numberOfOpenConnections--; 316 | } 317 | } 318 | 319 | void removeConnectionWithSocketId(int fd) 320 | { 321 | 322 | for (int i=0;icloseConnection(); 325 | free(peerConnectionDetails[i]); 326 | peerConnectionDetails[i]=0; 327 | numberOfOpenConnections--; 328 | } 329 | 330 | } 331 | TCPSocketConnection* getConnectionDetailsForId(int id) 332 | { 333 | return peerConnectionDetails[id]; 334 | } 335 | 336 | 337 | void listConnections() 338 | { 339 | for(int i=0;igetDestinationHostName(),peerConnectionDetails[i]->getDestinationIP(),peerConnectionDetails[i]->getDestinationPort()); 343 | } 344 | } 345 | 346 | // Internal methods 347 | 348 | void displayServerIPList() 349 | { 350 | for(int i=0;isendData(serverListMssg); 421 | } 422 | } 423 | free(serverListMssg); 424 | } 425 | // Interaction with shell methods 426 | void registerOnServer() 427 | { 428 | TCPSocketConnection *serverConn=new TCPSocketConnection(SERVERIP,SERVERPORT,0); 429 | serverConn->sendData("RegisterRequest\n"); 430 | } 431 | 432 | bool completeRequestAndCheckValidity(char *param1, char* param2 , int *port,char **finalIP,char **errStr) 433 | { 434 | // param1-->hostname/ip 435 | // param2--->port 436 | int tentPort=atoi(param2); 437 | bool foundMatch=false; 438 | if(tentPort==localPort&&(!strcmp(param1,localHostName)||!strcmp(param1,hostIP))) 439 | { 440 | strcpy(*errStr,"Self Connections are not allowed.\n"); 441 | return false; 442 | } 443 | if(numberOfOpenConnections==4) 444 | { 445 | strcpy(*errStr,"Maximum number of connections has been reached.\n"); 446 | return false; 447 | } 448 | for(int i=0;igetDestinationPort()&&strcmp(peerConnectionDetails[i]->getDestinationIP(),*finalIP)==0) 481 | { 482 | strcpy(*errStr,"Duplicate connections are not allowed.\n"); 483 | return false; 484 | } 485 | } 486 | } 487 | *port=tentPort; 488 | return true; 489 | 490 | } 491 | 492 | bool terminateConnection(int id,bool force) 493 | { 494 | if(id==1&&!force) 495 | return false; 496 | if(peerConnectionDetails[id-1]) 497 | { 498 | peerConnectionDetails[id-1]->closeConnection(); 499 | free(peerConnectionDetails[id-1]); 500 | peerConnectionDetails[id-1]=0; 501 | numberOfOpenConnections--; 502 | 503 | } 504 | return true; 505 | } 506 | 507 | void terminateAllConnections() 508 | { 509 | for (int i=1;i<=MAXCLIENTS;i++) 510 | { 511 | terminateConnection(i,true); 512 | } 513 | } 514 | 515 | void downloadMissedChunks(TCPSocketConnection *conn) 516 | { 517 | if(numberOfMissedChunks==0) 518 | { 519 | printf("\nDownload complete!!\n"); 520 | return; 521 | } 522 | 523 | 524 | if(conn==NULL) // just been initiated.thus we have to loop 525 | { 526 | for(int i=1;iisConnectionValid()) 532 | { 533 | FileChunkDetails *chunk=missedChunks[--numberOfMissedChunks]; 534 | peerConnectionDetails[i]->assignFileChunk(chunk); 535 | char fileReqMssg[1024]; 536 | sprintf(fileReqMssg,"FileRequest\n%s\n%d\n%d\n",chunk->getFileName(),chunk->getStartByte(),chunk->getChunkSize()); 537 | peerConnectionDetails[i]->sendData(fileReqMssg); 538 | 539 | } 540 | } 541 | } 542 | else 543 | { 544 | FileChunkDetails *chunk=missedChunks[--numberOfMissedChunks]; 545 | conn->assignFileChunk(chunk); 546 | char fileReqMssg[1024]; 547 | sprintf(fileReqMssg,"FileRequest\n%s\n%d\n%d\n",chunk->getFileName(),chunk->getStartByte(),chunk->getChunkSize()); 548 | conn->sendData(fileReqMssg); 549 | 550 | } 551 | 552 | 553 | } 554 | 555 | //if conn is null then it is the first case with the iteration 556 | void downloadFile(char *fileName,int chunkSize, int tentativeSize,TCPSocketConnection *conn) 557 | { 558 | static int sChunkSize=chunkSize; 559 | 560 | if(tentativeSize>0&&lastWrittenByte>=tentativeSize) 561 | { 562 | 563 | downloadActive=false; 564 | downloadMissedChunks(NULL); 565 | return; 566 | 567 | } 568 | 569 | if(!conn) 570 | { 571 | for(int i=1;iisConnectionValid()) 574 | { 575 | FileChunkDetails *chunk=new FileChunkDetails(fileName,lastWrittenByte,sChunkSize); 576 | peerConnectionDetails[i]->assignFileChunk(chunk); 577 | char fileReqMssg[1024]; 578 | sprintf(fileReqMssg,"FileRequest\n%s\n%d\n%d\n",fileName,lastWrittenByte,sChunkSize); 579 | peerConnectionDetails[i]->sendData(fileReqMssg); 580 | lastWrittenByte+=sChunkSize; 581 | } 582 | 583 | } 584 | } 585 | else 586 | { 587 | FileChunkDetails *chunk=new FileChunkDetails(fileName,lastWrittenByte,sChunkSize); 588 | conn->assignFileChunk(chunk); 589 | char fileReqMssg[1024]; 590 | sprintf(fileReqMssg,"FileRequest\n%s\n%d\n%d\n",fileName,lastWrittenByte,sChunkSize); 591 | conn->sendData(fileReqMssg); 592 | lastWrittenByte+=sChunkSize; 593 | } 594 | 595 | } 596 | 597 | void resetToPrompt() 598 | { 599 | if(downloadActive) 600 | return; 601 | 602 | printf(PROMPTVAR); 603 | fflush(stdout); 604 | } 605 | 606 | 607 | void displayShell() 608 | { 609 | //printf("displayShell"); 610 | 611 | //printf(PROMPTVAR); 612 | //while(1) 613 | //{ 614 | char inputLine[1024]; 615 | 616 | //fflush(stdout); 617 | fgets(inputLine,1024,stdin); 618 | char *command;//[30]; 619 | command=strtok(inputLine,"\n"); 620 | command=strtok(inputLine," "); 621 | // strcpy(command,strtok(inputLine,"\n")); 622 | //strcpy(command,strtok(inputLine," ")); 623 | //printf("command:%s\n",command); 624 | if(!strcmp(command,"HELP")) 625 | { 626 | printf("No help available\n"); 627 | resetToPrompt(); 628 | 629 | 630 | } 631 | else if(!strcmp(command,"MYIP")) 632 | { 633 | printf("%s\n",hostIP); 634 | resetToPrompt(); 635 | } 636 | else if(!strcmp(command,"MYPORT")) 637 | { 638 | printf("%d\n",localPort); 639 | resetToPrompt(); 640 | } 641 | else if(!strcmp(command,"REGISTER")) 642 | { 643 | if(isServer) 644 | { 645 | printf("Invalid Command\n"); 646 | resetToPrompt(); 647 | return; 648 | } 649 | char *tempServerIP;//[40]; 650 | //strcpy(tempServerIP,strtok(NULL," ")); 651 | tempServerIP=strtok(NULL," "); 652 | char *portStr;//[5]; 653 | portStr=strtok(NULL," "); 654 | //strcpy(portStr,strtok(NULL," ")); 655 | 656 | if(!tempServerIP||!portStr|| !strlen(tempServerIP)||!strlen(portStr)) 657 | { 658 | printf("Invalid Command Format.\n"); 659 | resetToPrompt(); 660 | } 661 | else if (peerConnectionDetails[0]) 662 | { 663 | printf("You are already registered to a server.\n"); 664 | resetToPrompt(); 665 | } 666 | else 667 | { 668 | // if(strcmp(tempServerIP,SERVERIP)||atoi(portStr)!=SERVERPORT) 669 | // { 670 | // printf("Invalid Details\n"); 671 | // resetToPrompt(); 672 | // return; 673 | // } 674 | printf("Trying to register....\n"); 675 | TCPSocketConnection *serverRegisterConn=new TCPSocketConnection(tempServerIP,atoi(portStr),0); 676 | char registerReqMessage[1024]; 677 | sprintf(registerReqMessage,"RegisterRequest\n%s\n%d\n%s\n",hostIP,localPort,localHostName); 678 | serverRegisterConn->setDestinationHostName(SERVERHOSTNAME); 679 | serverRegisterConn->sendData(registerReqMessage); 680 | addConnection(serverRegisterConn); 681 | //raise(10); 682 | } 683 | } 684 | else if(!strcmp(command,"CONNECT")) 685 | { 686 | if(isServer) 687 | { 688 | printf("Invalid Command\n"); 689 | resetToPrompt(); 690 | return; 691 | } 692 | char *peerIP;//[40]; 693 | //strcpy(tempServerIP,strtok(NULL," ")); 694 | peerIP=strtok(NULL," "); 695 | char *portStr;//[5]; 696 | portStr=strtok(NULL," "); 697 | //if(!strlen(peerIP)||strlen(portStr)) 698 | if(!peerIP||!portStr|| !strlen(peerIP)||!strlen(portStr)) 699 | printf("Invalid Command Format.\n"); 700 | else 701 | { 702 | // check for the validity of the connection 703 | char *fIP=(char*)malloc(40); 704 | int fPort; 705 | char *errString=(char*)malloc(500); 706 | bool status=completeRequestAndCheckValidity(peerIP,portStr,&fPort,&fIP,&errString); 707 | if(!status) 708 | { 709 | printf("%s",errString); 710 | free(errString); 711 | resetToPrompt(); 712 | return; 713 | } 714 | printf("Trying to connect to %s at port %d\n",fIP,fPort); 715 | TCPSocketConnection *peerConnectConn=new TCPSocketConnection(fIP,fPort,0); 716 | char connectReqMessage[1024]; 717 | sprintf(connectReqMessage,"ConnectRequest\n%s\n%d\n%s\n",hostIP,localPort,localHostName); 718 | peerConnectConn->sendData(connectReqMessage); 719 | addConnection(peerConnectConn); 720 | free(fIP); 721 | //resetToPrompt(); 722 | 723 | } 724 | 725 | } 726 | else if(!strcmp(command,"LIST")) 727 | { 728 | listConnections(); 729 | resetToPrompt(); 730 | 731 | } 732 | 733 | else if(!strcmp(command,"DOWNLOAD")) 734 | { 735 | if(isServer) 736 | { 737 | printf("Invalid Command\n"); 738 | resetToPrompt(); 739 | return; 740 | } 741 | 742 | char *fileName=strtok(NULL," "); 743 | char *chunkSizeStr=strtok(NULL," "); 744 | if(!fileName||!chunkSizeStr|| !strlen(fileName)||!strlen(chunkSizeStr)) 745 | printf("Invalid Command Format.\n"); 746 | else 747 | { 748 | downloadActive=true; 749 | lastWrittenByte=0; 750 | downloadFile(fileName,atoi(chunkSizeStr),-1,NULL); 751 | } 752 | printf("Downloading %s...\n",fileName); 753 | } 754 | 755 | else if(!strcmp(command,"TERMINATE")) 756 | { 757 | char *idStr; 758 | idStr=strtok(NULL," "); 759 | if(strlen(idStr)==0) 760 | printf("Invalid Usage.\n"); 761 | else 762 | { 763 | if(terminateConnection(atoi(idStr),false)) 764 | printf("Connection Terminated.\n"); 765 | else 766 | printf("Operation not permitted.\n"); 767 | } 768 | 769 | 770 | resetToPrompt(); 771 | } 772 | else if(!strcmp(command,"EXIT")) 773 | { 774 | terminateAllConnections(); 775 | printf("\n*** Transferred %lld bytes in %lld us\n",totalBytesTransferred,totalTimeInMicroSecs); 776 | exit(0); 777 | } 778 | 779 | else if(!strcmp(command,"SIP")) 780 | { 781 | displayServerIPList(); 782 | resetToPrompt(); 783 | } 784 | else if(!strcmp(command,"CREATOR")) 785 | { 786 | printf("Name:Subhranil Banerjee\nUBITName:subhrani\nEmail:subhrani@buffalo.edu\n"); 787 | resetToPrompt(); 788 | } 789 | 790 | else 791 | { 792 | printf("Command not found.\n"); 793 | resetToPrompt(); 794 | } 795 | 796 | //} 797 | 798 | } 799 | 800 | 801 | void handleDataOnSocket(char* message,TCPSocketConnection* connObj,int numberOfBytesRecvd, long long int usecs) 802 | { 803 | //printf("message:%s",message); 804 | char messageType[30]; 805 | char *tempMessageBuffer=(char*)malloc(numberOfBytesRecvd); 806 | memcpy(tempMessageBuffer,message,numberOfBytesRecvd); 807 | //int totalMessageLength=strlen(message); 808 | strcpy(messageType,strtok(message,"\n")); 809 | 810 | if(strcmp(messageType,"FileRequest")==0) 811 | { 812 | char *fileNameToSend=strtok(NULL,"\n"); 813 | long long int startByte=atoll(strtok(NULL,"\n")); 814 | int chunkSize=atoi(strtok(NULL,"\n")); 815 | 816 | char *dataBuffer=(char*)malloc(chunkSize+1); 817 | int fileSendDesc=open(fileNameToSend,O_RDONLY); 818 | lseek(fileSendDesc,startByte,SEEK_SET); 819 | int numberOfBytesRead=read(fileSendDesc,dataBuffer,chunkSize); 820 | dataBuffer[numberOfBytesRead]=0; 821 | long long int fileSize=getFileSize(fileNameToSend); 822 | int numberOfBytesSent=0; 823 | char headerMessage[1024]; 824 | sprintf(headerMessage,"FileResponse\n%s\n%lld\n%lld\n%lld%s",fileNameToSend,fileSize,startByte,(startByte+numberOfBytesRead),headerDelim); 825 | int totalWindowSize=strlen(headerMessage)+numberOfBytesRead; 826 | char *totalMessage=(char*)malloc(totalWindowSize); 827 | memcpy(totalMessage,headerMessage,strlen(headerMessage)); 828 | 829 | // cannot use sprintf here since the databuffer may not be a string 830 | memcpy(totalMessage+strlen(headerMessage),dataBuffer,numberOfBytesRead); 831 | //sprintf(totalMessage,"%s%s%s%s",headerMessage,headerDelim,dataBuffer,headerDelim); 832 | struct timeval startTime,endTime; 833 | gettimeofday(&startTime,NULL); 834 | totalBytesTransferred+=(long long int)connObj->sendData(totalMessage,totalWindowSize); 835 | gettimeofday(&endTime,NULL); 836 | totalTimeInMicroSecs+=100000LL*(long long int)(endTime.tv_sec-startTime.tv_sec)+(long long int)(endTime.tv_usec-startTime.tv_usec); 837 | close(fileSendDesc); 838 | free(totalMessage); 839 | free(dataBuffer); 840 | 841 | } 842 | else if(strcmp(messageType,"FileResponse")==0) 843 | { 844 | 845 | char header[1200]=""; 846 | strcpy(header,strtok(NULL,headerDelim)); 847 | totalBytesTransferred+=numberOfBytesRecvd; 848 | totalTimeInMicroSecs+=usecs; 849 | int contentLength=numberOfBytesRecvd-strlen(messageType)-strlen(header)-11; 850 | char* indexofDelim=strstr(tempMessageBuffer,headerDelim); 851 | //char *contents=(char*)malloc(totalMessageLength-strlen(header)); 852 | //strcpy(contents,strtok(NULL,"\n")); 853 | // parse the header 854 | //char fileName0[1024]=""; 855 | // strcpy(fileName,strtok(header,headerDelim)); 856 | // int fileSize=atoi(strtok(NULL,headerDelim)); 857 | // int startByte=atoi(strtok(NULL,headerDelim)); 858 | // int endByte=atoi(strtok(NULL,headerDelim)); 859 | 860 | char *fileName=strtok(header,"\n"); 861 | long long int fileSize=atoll(strtok(NULL,"\n")); 862 | long long int startByte=atoll(strtok(NULL,"\n")); 863 | long long endByte=atoll(header); 864 | 865 | 866 | // printf("MessageType:%s\nFileName:%s\nSize:%d\nStart:%d\nEnd:%d-->%s\n\n\n",messageType,fileName,fileSize,startByte,endByte,contents); 867 | 868 | // open file for writing 869 | char destPath[1024]=""; 870 | sprintf(destPath,fileName); 871 | //int writefd=creat(destPath,O_EXCL|S_IRUSR | S_IWUSR); 872 | int writefd=open(destPath,O_WRONLY|O_CREAT| O_EXCL, S_IRUSR | S_IWUSR | S_IROTH); 873 | if(writefd<0) 874 | { 875 | if(errno==EEXIST) 876 | { 877 | //printf("file already exists"); 878 | writefd=open(destPath,O_WRONLY); 879 | //printf("error in open%d",errno); 880 | } 881 | 882 | } 883 | 884 | int offset,numberofbytes=0; 885 | //while(numberofbytes=fileSize) 896 | 897 | 898 | //free(contents); 899 | if(downloadActive) 900 | downloadFile(fileName,numberofbytes,fileSize,connObj); 901 | else 902 | downloadMissedChunks(connObj); 903 | // if(endByte>=fileSize) 904 | // { 905 | // // check for missing chunks in aray 906 | // printf("Donwload completed!!\n%s",PROMPTVAR); 907 | // } 908 | // else 909 | // { 910 | // printf("endbyte :%d filesize:%d ==> so calling downlaod \n",endByte,fileSize); 911 | // 912 | // } 913 | 914 | 915 | 916 | } 917 | else if(strcmp(messageType,"RegisterRequest")==0) // this is applicable only in the case of ther server 918 | { 919 | if(isServer) 920 | { 921 | char *ip=strtok(NULL,"\n"); 922 | char *port=strtok(NULL,"\n"); 923 | char *hostname=strtok(NULL,"\n"); 924 | if(strlen(ip)>0&&strlen(port)>0&&strlen(hostname)>0) 925 | { 926 | connObj->setDestinationIP(ip); 927 | connObj->setDestinationPort(atoi(port)); 928 | connObj->setDestinationHostName(hostname); 929 | addToServerList(ip,atoi(port),hostname); 930 | connObj->sendData("RegisterAcknowledged\n"); // the server will always try to add the client 931 | //addConnection(connObj); 932 | sleep(1); 933 | broadcastServerList(); 934 | connObj->validateConnection(); 935 | } 936 | else 937 | connObj->sendData("RegisterRequestIncomplete\n"); 938 | 939 | } 940 | else 941 | connObj->sendData("RegisterRequestInvalid\n"); 942 | 943 | } 944 | else if (strcmp(messageType,"RegisterRequestIncomplete")==0) 945 | removeConnectionWithSocketId(connObj->getSocketId()); 946 | 947 | else if(strcmp(messageType,"RegisterAcknowledged")==0) // will be received by a client trying to register 948 | { 949 | // USE THIS PART TO DO WHATEVER YOU WANT WITH THE SEVER IP LIST 950 | 951 | // char *scanStartPt=strstr(tempMessageBuffer,"\n"); 952 | // 953 | // memcpy(serverIPList,scanStartPt+1,numberOfBytesRecvd-strlen(messageType)-1); 954 | // displayServerIPList(); 955 | 956 | 957 | connObj->validateConnection(); 958 | //addConnection(connObj); // assumption: that register will take place b4 any connect 959 | printf("Registration with server successful.\n"); 960 | resetToPrompt(); 961 | } 962 | else if(strcmp(messageType,"RegisterRequestInvalid")==0) 963 | { 964 | printf("You can only register with the server.\n"); 965 | removeConnectionWithSocketId(connObj->getSocketId()); 966 | resetToPrompt(); 967 | 968 | } 969 | 970 | else if(strcmp(messageType,"ConnectRequest")==0) 971 | { 972 | // if(addConnection(connObj)) 973 | // connObj->sendData("ConnectAccepted"); 974 | // else 975 | // connObj->sendData("ConnectRejected"); 976 | 977 | 978 | if(isServer) 979 | connObj->sendData("ConnectRequestInvalid\n"); 980 | 981 | else 982 | { 983 | 984 | char *ip=strtok(NULL,"\n"); 985 | char *port=strtok(NULL,"\n"); 986 | char *hostname=strtok(NULL,"\n"); 987 | if(strlen(ip)>0&&strlen(port)>0&&strlen(hostname)>0&&numberOfOpenConnections<=4) 988 | { 989 | 990 | 991 | connObj->setDestinationIP(ip); 992 | connObj->setDestinationPort(atoi(port)); 993 | connObj->setDestinationHostName(hostname); 994 | connObj->sendData("ConnectAccepted\n"); // the server will always try to add the client 995 | connObj->validateConnection(); 996 | //addConnection(connObj); 997 | 998 | } 999 | else 1000 | connObj->sendData("ConnectRejected\n"); 1001 | 1002 | } 1003 | 1004 | } 1005 | 1006 | else if(strcmp(messageType,"ConnectRequestInvalid")==0) 1007 | { 1008 | printf("You cannot send connect request to a server.\n"); 1009 | removeConnectionWithSocketId(connObj->getSocketId()); 1010 | 1011 | } 1012 | 1013 | else if(strcmp(messageType,"ConnectAccepted")==0) // will be received by the sender of the request 1014 | { 1015 | 1016 | connObj->validateConnection(); 1017 | printf("Successfully connected to peer.\n"); 1018 | resetToPrompt(); 1019 | } 1020 | else if(strcmp(messageType,"ConnectRejected")==0) 1021 | { 1022 | 1023 | removeConnectionWithSocketId(connObj->getSocketId()); 1024 | printf("Connection with host failed.\n"); 1025 | resetToPrompt(); 1026 | } 1027 | else if(strcmp(messageType,"ServerListUpdate")==0) 1028 | { 1029 | memset(serverIPList,0,MAXCLIENTS*sizeof(PeerDetails)); 1030 | 1031 | char* lineFeed=strtok(NULL,"\n"); 1032 | char *tempLine=lineFeed;//(char*)malloc(strlen(lineFeed)); 1033 | //strcpy(tempLine,lineFeed); 1034 | 1035 | int index=0; 1036 | char* firstToken; 1037 | firstToken=strtok(tempLine,":"); 1038 | while(firstToken) 1039 | { 1040 | 1041 | 1042 | strcpy(serverIPList[index].IP,firstToken); 1043 | strcpy(serverIPList[index].hostName,strtok(NULL,":")); 1044 | serverIPList[index].port=atoi(strtok(NULL,":")); 1045 | firstToken=strtok(NULL,":"); 1046 | //sscanf(lineFeed,"%s %s%d",serverIPList[index].IP,serverIPList[index].hostName,&serverIPList[index].port); 1047 | 1048 | 1049 | index++; 1050 | } 1051 | //free(tempLine); 1052 | //char *scanStartPt=strstr(tempMessageBuffer,"\n"); 1053 | 1054 | //memcpy(&serverIPList,scanStartPt+1,numberOfBytesRecvd-strlen(messageType)-1); 1055 | //displayServerIPList(); 1056 | free(tempMessageBuffer); 1057 | printf("Server List updated\n"); 1058 | resetToPrompt(); 1059 | } 1060 | 1061 | } 1062 | 1063 | 1064 | void handleSocketBehaviour(void) 1065 | { 1066 | //printf("handleSocketBehaviour"); 1067 | 1068 | int sendFileDesc,recvFileDesc; 1069 | 1070 | /* observedSockets file descriptor list and max value */ 1071 | fd_set observedSockets; 1072 | int fdmax; 1073 | 1074 | int mainSocket; 1075 | 1076 | memset(peerConnectionDetails,0,MAXCLIENTS*sizeof(TCPSocketConnection *)); 1077 | 1078 | // defining the address for the main socket 1079 | 1080 | SocketAddressInfo *socketAddress; // this structure basically stores info about the socket address 1081 | socketAddress=(SocketAddressInfo*)malloc(sizeof(SocketAddressInfo)); 1082 | socketAddress->sin_family=AF_INET; 1083 | inet_pton(socketAddress->sin_family,hostIP,&(socketAddress->sin_addr)); 1084 | socketAddress->sin_port=htons(localPort); 1085 | 1086 | //create a socket for accepting incoming connections 1087 | 1088 | mainSocket=socket(AF_INET,SOCK_STREAM,0); 1089 | if(mainSocket==-1) 1090 | { 1091 | printf("Error in creating socket"); 1092 | exit(0); 1093 | } 1094 | 1095 | 1096 | // bind the spcket to the addressinfo 1097 | 1098 | if(bind(mainSocket,(struct sockaddr*)socketAddress,sizeof(SocketAddressInfo))==-1) 1099 | { 1100 | printf("Error in binding socket IP address"); 1101 | exit(0); 1102 | } 1103 | 1104 | 1105 | 1106 | // listen for incoming connections 1107 | if(listen(mainSocket,10)==-1) 1108 | { 1109 | printf("Error in listening"); 1110 | exit(0); 1111 | } 1112 | 1113 | 1114 | // Begin code for socket listening 1115 | 1116 | //printf("Server running..."); 1117 | /* clear the observedSockets and temp sets */ 1118 | FD_ZERO(&observedSockets); 1119 | 1120 | // run loop for observing sockets 1121 | 1122 | while(true) 1123 | { 1124 | /* add the listener to the observedSockets set */ 1125 | FD_SET(mainSocket, &observedSockets); 1126 | if(!downloadActive) 1127 | FD_SET(0,&observedSockets); 1128 | /* keep track of the biggest file descriptor */ 1129 | fdmax = mainSocket ; /* so far, it's this one*/ 1130 | 1131 | // add the client sockets for observation 1132 | for(int i=0;igetSocketId(); 1137 | if(tempDesc>0) // already assigned to a valid connection 1138 | { 1139 | FD_SET(tempDesc,&observedSockets); 1140 | if(tempDesc>fdmax) 1141 | fdmax=tempDesc; 1142 | } 1143 | 1144 | } 1145 | 1146 | struct timeval timeout; 1147 | timeout.tv_sec=1; 1148 | timeout.tv_usec=0; 1149 | int activity=select(fdmax+1,&observedSockets,NULL,NULL,&timeout); // blocking all until there is some activity on any of the sockets 1150 | if(activity<0) 1151 | { 1152 | if(errno==EINTR) 1153 | continue; 1154 | printf("error in select"); 1155 | return ; 1156 | } 1157 | if(FD_ISSET(mainSocket,&observedSockets)) // .. there has been activity on the mainSocket. thus there s a new connection that needs to be added 1158 | { 1159 | SocketAddressInfo clientSocketInfo; 1160 | int sizeOfSocketData=sizeof(clientSocketInfo); 1161 | int conn=accept(mainSocket,(struct sockaddr*)&clientSocketInfo,(socklen_t*)&sizeOfSocketData); 1162 | // add the connection temp. 1163 | TCPSocketConnection *newConn=new TCPSocketConnection(&clientSocketInfo,conn); 1164 | addConnection(newConn); 1165 | 1166 | // printf("%added connection with id:%d",conn); 1167 | 1168 | } 1169 | else if(FD_ISSET(0,&observedSockets)) 1170 | { 1171 | displayShell(); 1172 | } 1173 | else // there is some activity on the other open sockets possibly incoming data 1174 | { 1175 | for(int i=0;igetSocketId(); 1180 | if(tempDesc>0) 1181 | { 1182 | if(FD_ISSET(tempDesc,&observedSockets)) 1183 | { 1184 | char incomingMessage[MAXPACKETSIZE]; 1185 | int numberOfBytesRecvd=0; 1186 | 1187 | struct timeval startTime,endTime; 1188 | gettimeofday(&startTime,NULL); 1189 | numberOfBytesRecvd=recv(tempDesc,&incomingMessage,MAXPACKETSIZE-1,0); 1190 | gettimeofday(&endTime,NULL); 1191 | 1192 | if(numberOfBytesRecvd<=0) //connection terminated by peer 1193 | { 1194 | 1195 | //peerSocketIds[i]=0; 1196 | FD_CLR(tempDesc,&observedSockets); 1197 | 1198 | if(isServer) 1199 | { 1200 | removeFromServerList(getConnectionDetailsForId(i)->getDestinationIP(),getConnectionDetailsForId(i)->getDestinationPort()); 1201 | } 1202 | missedChunks[numberOfMissedChunks++]=getConnectionDetailsForId(i)->assignedChunk(); 1203 | removeConnctionWithConnectionId(i); 1204 | broadcastServerList(); 1205 | 1206 | printf("connection terminated for host#%d-->%d\n",i,numberOfBytesRecvd); 1207 | } 1208 | else 1209 | { 1210 | //dataBuffer[numberOfBytesRecvd]='\0'; 1211 | long long int recvTime=100000LL*(long long int)(endTime.tv_sec-startTime.tv_sec)+(long long int)(endTime.tv_usec-startTime.tv_usec); 1212 | handleDataOnSocket(incomingMessage,peerConnectionDetails[i],numberOfBytesRecvd,recvTime); 1213 | 1214 | 1215 | } 1216 | } 1217 | } 1218 | } 1219 | 1220 | } 1221 | 1222 | 1223 | 1224 | } 1225 | 1226 | 1227 | } 1228 | 1229 | 1230 | 1231 | 1232 | int main(int argc, char*argv[]) 1233 | { 1234 | if(argc!=3) 1235 | { 1236 | printf("Invalid usage\n"); 1237 | exit(1); 1238 | } 1239 | 1240 | isServer=(strcmp(argv[1],"s")==0); 1241 | localPort=atoi(argv[2]); 1242 | getLocalIP(); 1243 | resetToPrompt(); 1244 | //pthread_t socketThread; 1245 | handleSocketBehaviour(); 1246 | //pthread_create( &socketThread,NULL,handleSocketBehaviour,0); 1247 | 1248 | 1249 | //displayShell(); 1250 | 1251 | 1252 | //pthread_join(socketThread,NULL); 1253 | return 0; 1254 | 1255 | } 1256 | --------------------------------------------------------------------------------