Routes* getRoutes(Graph* graph, int vertex) { if (graph->vertices > 32) { return NULL; } Routes *routes = createRoutes(graph->vertices); unsigned int endMask = 0; endMask = ~endMask; endMask >>= (32 - graph->vertices); unsigned int visited = 0; routes->weight[vertex] = 0; routes->from[vertex] = vertex; int current = vertex; while ((visited != endMask) && (current != 0)) { int i = current; for (int j = 1; j <= graph->vertices; j++) { if (graph->a[i][j] == 0) { continue; } int weight = routes->weight[i] + graph->a[i][j]; unsigned int jMask = 1; jMask <<= j - 1; if (!(jMask & visited) && ((weight < routes->weight[j]) || (routes->weight[j] == 0))) { routes->weight[j] = weight; routes->from[j] = current; } } unsigned int mask = 1; mask <<= current - 1; visited |= mask; current = getNearestVertex(routes, visited); } return routes; }
int main(int argc, char **argv) { // ------------------------------------------------------------------------ // Handle commandline arguments if (argc < 5) { printf("usage: emulator -p <port> -f <filename>\n"); exit(1); } char *portStr = NULL; const char *filename = NULL; int cmd; while ((cmd = getopt(argc, argv, "p:f:")) != -1) { switch(cmd) { case 'p': portStr = optarg; break; case 'f': filename = optarg; break; case '?': if (optopt == 'p' || optopt == 'f') fprintf(stderr, "Option -%c requires an argument.\n", optopt); else if (isprint(optopt)) fprintf(stderr, "Unknown option -%c.\n", optopt); else fprintf(stderr, "Unknown option character '\\x%x'.\n", optopt); exit(EXIT_FAILURE); break; default: printf("Unhandled argument: %d\n", cmd); exit(EXIT_FAILURE); } } printf("Port : %s\n", portStr); printf("File Name : %s\n", filename); // Convert program args to values int emulPort = atoi(portStr); int maxTime = 1500; int minTime = 500; // Validate the argument values if (emulPort <= 1024 ||emulPort >= 65536) ferrorExit("Invalid emul port"); puts(""); srand(time(NULL)); initLog("log_file.txt"); // ------------------------------------------------------------------------ // Setup emul address info struct addrinfo ehints; bzero(&ehints, sizeof(struct addrinfo)); ehints.ai_family = AF_INET; ehints.ai_socktype = SOCK_DGRAM; ehints.ai_flags = AI_PASSIVE; char localhost[80]; gethostname(localhost, sizeof(localhost)); // Get the emul's address info struct addrinfo *emulinfo; int errcode = getaddrinfo(localhost, portStr, &ehints, &emulinfo); if (errcode != 0) { fprintf(stderr, "emul getaddrinfo: %s\n", gai_strerror(errcode)); exit(EXIT_FAILURE); } // Loop through all the results of getaddrinfo and try to create a socket for emul int sockfd; struct addrinfo *sp; for(sp = emulinfo; sp != NULL; sp = sp->ai_next) { // Try to create a new socket sockfd = socket(sp->ai_family, sp->ai_socktype, sp->ai_protocol); if (sockfd == -1) { perror("Socket error"); continue; } // Try to bind the socket if (bind(sockfd, sp->ai_addr, sp->ai_addrlen) == -1) { perror("Bind error"); close(sockfd); continue; } break; } if (sp == NULL) perrorExit("Send socket creation failed"); else printf("emul socket created.\n"); struct sockaddr_in *tmp = (struct sockaddr_in *)sp->ai_addr; unsigned long eIpAddr = tmp->sin_addr.s_addr; //printf("eIpAddr: %lu\n", eIpAddr); initTable(filename, tmp); exit(0); // ------------------------------------------------------------------------ // The Big Loop of DOOM struct sockaddr_in *nextSock; int shouldForward; fd_set fds; struct timespec *tv = malloc(sizeof(struct timespec)); tv->tv_sec = (long) 0; tv->tv_nsec = 0; int retval = 0; int numRecv = 0; int routesMade = 0; unsigned long long start; struct packet *dpkt; struct ip_packet *pkt = malloc(sizeof(struct ip_packet)); void *msg = malloc(sizeof(struct ip_packet)); for (;;) { FD_ZERO(&fds); FD_SET(sockfd, &fds); start = getTimeMS(); retval = pselect(sockfd + 1, &fds, NULL, NULL, tv, NULL); // ------------------------------------------------------------------------ // receiving half if (retval > 0 /*&& routesMade == 1*/) { // Receive and forward packet printf("retval > 0\n"); bzero(msg, sizeof(struct ip_packet)); size_t bytesRecvd = recvfrom(sockfd, msg, sizeof(struct ip_packet), 0, NULL, NULL); if (bytesRecvd == -1) { perror("Recvfrom error"); fprintf(stderr, "Failed/incomplete receive: ignoring\n"); continue; } // Deserialize the message into a packet bzero(pkt, sizeof(struct ip_packet)); deserializeIpPacket(msg, pkt); dpkt = (struct packet *)pkt->payload; printIpPacketInfo(pkt, NULL); // Check packet type to see if any action needs to be taken nextSock = malloc(sizeof(struct sockaddr_in)); if (dpkt->type == 'T') { if (dpkt->len == 0) { bzero(nextSock, sizeof(struct sockaddr_in)); shouldForward = 1; nextSock->sin_family = AF_INET; nextSock->sin_addr.s_addr = htonl(pkt->src); nextSock->sin_port = htons(pkt->srcPort); pkt->src = eIpAddr; pkt->srcPort = emulPort; } else { dpkt->len--; shouldForward = nextHop(pkt, nextSock); } } else if (dpkt->type == 'S') { /*if ((pkt->dest == eIpAddr && pkt->destPort == emulPort) || dpkt->len == 0) { dpkt = createNeighborPkt(); bzero(pkt, sizeof(struct ip_packet)); pkt->length = dpkt->len + HEADER_SIZE; pkt->priority = 0; memcpy(pkt->payload, dpkt, sizeof(struct packet)); }*/ if (updateLSP(pkt)) { floodLSP(sockfd, tmp, pkt); } shouldForward = 0; routesMade = 0; } else { shouldForward = nextHop(pkt, nextSock); } // Forward the packet if there is an entry for it if (shouldForward) { printf("send packet\n"); //printf("socket is %lu %u", nextSock->sin_addr.s_addr, nextSock->sin_port); sendIpPacketTo(sockfd, pkt, (struct sockaddr*)nextSock); free(nextSock); } else { logP(pkt, "No forwarding entry found"); } // update timespec long sec = tv->tv_sec - (long)((getTimeMS() - start) / 1000); long nsec = tv->tv_nsec - (long)(1000000 * ((getTimeMS() - start) % 1000)); if (nsec < 0) { nsec = 1000000 * 1000 + nsec; sec--; } if (sec < 0 || !numRecv) { sec = 0; nsec = 0; } tv->tv_sec = sec; tv->tv_nsec = nsec; } if (retval == 0 || routesMade == 0) { // ------------------------------------------------------------------------ // refresh forward table printf("retval == 0\n"); if (retval == 0) { floodLSP(sockfd, tmp, NULL); } routesMade = createRoutes(tmp); int delay = minTime + (rand() % (maxTime - minTime)); tv->tv_sec = (long)delay / 1000; tv->tv_nsec = (long)(delay % 1000) * 1000000; } else { //printf("Sockfd = %d\n", sockfd); //printf("tv%d delay=%li s %li us\n", x, tv->tv_sec, tv->tv_nsec); perrorExit("Select()"); } } // Cleanup packets free(pkt); free(msg); }
int main(int argc, char **argv) { // ------------------------------------------------------------------------ // Handle commandline arguments if (argc != 5) { printf("usage: emulator -p <port> -f <filename>\n"); exit(1); } char *portStr = NULL; char *filename = NULL; int cmd; while ((cmd = getopt(argc, argv, "p:f:")) != -1) { switch(cmd) { case 'p': portStr = optarg; break; case 'f': filename = optarg; break; case '?': if (optopt == 'p' || optopt == 'f') fprintf(stderr, "Option -%c requires an argument.\n", optopt); else if (isprint(optopt)) fprintf(stderr, "Unknown option -%c.\n", optopt); else fprintf(stderr, "Unknown option character '\\x%x'.\n", optopt); exit(EXIT_FAILURE); break; default: printf("Unhandled argument: %d\n", cmd); exit(EXIT_FAILURE); } } printf("Port : %s\n", portStr); printf("Filename : %s\n", filename); // Convert program args to values int port = atoi(portStr); // Validate the argument values if (port < 1 || port > 65536) ferrorExit("Invalid port"); puts(""); // Read network topology struct entry **topology = readtopology(filename); printTopology(topology); // Create network routes from topology createRoutes(topology); // TODO: this is temporary, need to get sender address info from fwd table // Setup sender address info struct addrinfo ehints; bzero(&ehints, sizeof(struct addrinfo)); ehints.ai_family = AF_INET; ehints.ai_socktype = SOCK_DGRAM; ehints.ai_flags = 0; // Setup emu sending socket struct sockaddr_in emuaddr; int sockfd; if( (sockfd = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0)) == -1){ perrorExit("Socket error"); } emuaddr.sin_family = AF_INET; emuaddr.sin_port = htons(port); emuaddr.sin_addr.s_addr = INADDR_ANY; bzero(&(emuaddr.sin_zero), 8); if (bind(sockfd, (struct sockaddr*)&emuaddr, sizeof(emuaddr)) == -1) { close(sockfd); perrorExit("Bind error"); } printf("Emulator socket created on port:%d\n", port ); //------------------------------------------------------------------------- // BEGIN NETWORK EMULATION LOOP puts("Emulator waiting for packets...\n"); struct sockaddr_in recvAddr; socklen_t recvLen = sizeof(recvAddr); //socklen_t sendLen = sizeof(sendAddr); // HACK: Don't like hard coding this, but don't know any other way size_t MAX_HOST_LEN = 256; char name[MAX_HOST_LEN]; gethostname(name, MAX_HOST_LEN); //Need to just get lowest level dns name i.e. mumble-30 while (1) { void *msg = malloc(sizeof(struct packet)); bzero(msg, sizeof(struct packet)); size_t bytesRecvd; bytesRecvd = recvfrom(sockfd, msg, sizeof(struct packet), 0, (struct sockaddr *)&recvAddr, &recvLen); if (bytesRecvd != -1) { //printf("Received %d bytes\n", (int)bytesRecvd); // Deserialize the message into a packet struct packet *pkt = malloc(sizeof(struct packet)); bzero(pkt, sizeof(struct packet)); deserializePacket(msg, pkt); struct addrinfo entryHints; bzero(&entryHints, sizeof(struct addrinfo)); entryHints.ai_family = AF_INET; entryHints.ai_socktype = SOCK_DGRAM; entryHints.ai_flags = 0; } } if (close(sockfd) == -1) perrorExit("Close error"); else puts("Connection closed.\n"); // All done! exit(EXIT_SUCCESS); }