#include #include #include #include #include #include #include #include #define WIN32_LEAN_AND_MEAN //#include #include #include #include #include #include #include #include #include "math.h" #include "datatypes.h" #include "Helpers.h" #include int CheckIfInList(struct HostID HID, std::list &List) { // returns 1 if HID is in List std::list::iterator it; for (it=List.begin(); it!=List.end(); ++it) if (strcmp(it->IP,HID.IP)==0 && it->Port == HID.Port) return 1; return 0; } struct HostID SelectNeighbor(std::list &ActiveNeighbors, std::list &SemiActiveNeighbors, std::list &AllHosts, struct HostID &ThisHost) { // pick a host randomly from list of all hosts. If the selected host is already active or semi-active, then pick again int cnt=0; while (1) { if (cnt++ > 10000) break; int HostToPick = floor((double)rand()/(double)RAND_MAX*AllHosts.size()); // pick a random number from 0 to the size of AllHosts if (HostToPick == AllHosts.size()) HostToPick--; // just in case std::list::iterator it; for (it=AllHosts.begin(); it!=AllHosts.end(); ++it) { if (HostToPick==0) { if (CheckIfInList(*it,ActiveNeighbors)==0 && CheckIfInList(*it,SemiActiveNeighbors)==0 && (strcmp(it->IP,ThisHost.IP)!=0||it->Port!=ThisHost.Port) ) return *it; else break; // select another } HostToPick--; } } printf("!!!!!Failed to select from the list of all hosts that is not either active or semi-active. \n"); return AllHosts.front(); // this should never happen } void CheckIfNeighborsHaveSentHello(std::list &Neighbors) { // this checks if a neighbors has sent a hello within the past 40 seconds or not std::list::iterator it; std::list::iterator LastIt; struct timeb TimeBuffer; ftime( &TimeBuffer ); it=Neighbors.begin(); while (it!=Neighbors.end()) { int Del=0; if (TimeBuffer.time - it->LastHelloRec > 40) Del=1; LastIt = it; ++it; if (Del==1) Neighbors.erase(LastIt); } } void PrintPacketRecieved(struct PktStruct *pkt, struct HostID ThisHost) { // When the host has received a packet, this can be used to print the contents of the packet printf("GotPacket: %s:%d ----> %s:%d(me)\n",pkt->SenderIP,pkt->SenderPort,ThisHost.IP,ThisHost.Port); switch (pkt->Type) { case HELLO_PKT_TYPE: if (pkt->NumberOfRecentlyHeardNeighbors>0) { printf("advertising \n"); for (int i=0; iNumberOfRecentlyHeardNeighbors; i++) { printf(" %s:%d\n",pkt->RecentNeighbors[i].IP,pkt->RecentNeighbors[i].Port); } } printf("\n"); break; default: printf("unknown packet type\n"); } } void PrintPacketTransmitted(struct PktStruct *pkt, struct HostID Dest) { // When the host is about to send a packet, this can be used to print the contents of the packet to be sent printf("Sending packet %s:%d(me) --> %s:%d\n",pkt->SenderIP,pkt->SenderPort,Dest.IP,Dest.Port); switch (pkt->Type) { case HELLO_PKT_TYPE: if (pkt->NumberOfRecentlyHeardNeighbors>0) { printf("advertising \n"); for (int i=0; iNumberOfRecentlyHeardNeighbors; i++) { printf(" %s:%d\n",pkt->RecentNeighbors[i].IP,pkt->RecentNeighbors[i].Port); } } printf("\n"); break; default: printf("unknown packet type\n"); } } void PrintStatus(std::list &ActiveNeighbors, std::list &SemiActiveNeighbors, struct HostID TempNeighbor, int SearchingForNeighborFlag, int TimeBetweenPrints) { // This prints the current status // With TimeBetweenPrints, the time between prints can be controlled. Specifically, the status will not be printed out more frequenctly than TimeBetweenPrints static int LastTimePrinted = 0; struct timeb TimeBuffer; ftime( &TimeBuffer ); if (TimeBuffer.time - LastTimePrinted > TimeBetweenPrints) { printf("\n\n\nThere are %d neighbors and %d are required\n",ActiveNeighbors.size()+SemiActiveNeighbors.size(),DESIRE_NUMBER_OF_NEIGHBORS); if (SearchingForNeighborFlag==1) printf("Searching for a new neighbor: %s:%d\n",TempNeighbor.IP,TempNeighbor.Port); LastTimePrinted = TimeBuffer.time; std::list::iterator Ait; Ait=ActiveNeighbors.begin(); std::list::iterator Sit; Sit=SemiActiveNeighbors.begin(); printf("Active Neighbors Time SemiActive Time \n"); printf("----------------------------------------------------\n"); while (1) { if (Ait!=ActiveNeighbors.end() && Sit!=SemiActiveNeighbors.end()) { printf("%s:%d %d %s:%d %d\n",Ait->IP,Ait->Port, TimeBuffer.time-Ait->LastHelloRec, Sit->IP, Sit->Port, TimeBuffer.time-Sit->LastHelloRec); ++Ait; ++Sit; } else { if (Ait!=ActiveNeighbors.end()) { printf("%s:%d %d \n",Ait->IP,Ait->Port, TimeBuffer.time-Ait->LastHelloRec); ++Ait; } else { if (Sit!=SemiActiveNeighbors.end()) { printf(" %s:%d %d\n",Sit->IP, Sit->Port, TimeBuffer.time-Sit->LastHelloRec); ++Sit; } else break; } } } printf("-------------------------------------------------------\n\n"); } } void FillThisHostIP(struct HostID &ThisHost) { // This determines the host IP address and saves if in ThisHost.IP char MyIP[2000]; struct hostent * hp; struct sockaddr_in to; gethostname(MyIP,2000); hp = gethostbyname(MyIP); memcpy(&(to.sin_addr),hp->h_addr,hp->h_length); strcpy(ThisHost.IP,inet_ntoa(to.sin_addr)); } void ReadAllHostsList(char *fn, std::list &AllHosts) { // This reads the hosts IDs (IP and port) listed in file fn and puts the host IDs in AllHosts // This function should be called during initialization FILE *fptr; fptr = fopen(fn,"rt"); if (fptr==NULL) { printf("error: could not open file %s with list of all hosts\n",fn); exit(0); } char str[20]; int port; printf("possible neighbors: \n"); while (fscanf(fptr,"%s %d",str, &port)!=EOF ) { printf(" %s %d\n",str,port); struct HostID hid; strcpy(hid.IP,str); hid.Port=port; AllHosts.push_back(hid); } printf("\n"); fclose(fptr); }