//read topology.dat void getTopoData() { FILE *pFile; pFile = fopen("../topology/topology.dat","r"); if(pFile == NULL) { printf("open file error\n"); exit(-1); } char buf[128]; int lineCount=0; while (fgets(buf,sizeof(buf),pFile)!= NULL) { lineCount++; } if(lineCount<=0) { printf("no topology in file\n"); exit(-1); } //init topo data list allIdList=malloc(lineCount*2*sizeof(int)); nbIdList=malloc(lineCount*sizeof(int)); nbIpList=malloc(lineCount*sizeof(in_addr_t)); costList=malloc(lineCount*sizeof(int)); //get data from file char host1[32],host2[32]; int cost; int myId=topology_getMyNodeID(); nbCount=0; fseek(pFile,0,SEEK_SET); while(fscanf(pFile,"%s %s %d", host1, host2, &cost) > 0) { int id1=topology_getNodeIDfromname(host1); int id2=topology_getNodeIDfromname(host2); int i=0; for(;i<allCount;i++) { if(allIdList[i]==id1)break; } if(i==allCount)allIdList[allCount++]=id1; i=0; for(;i<allCount;i++) { if(allIdList[i]==id2)break; } if(i==allCount)allIdList[allCount++]=id2; //neighbor if(id1==myId) { nbIdList[nbCount]=id2; nbIpList[nbCount]=topology_getNodeIPfromname(host2); costList[nbCount]=cost; if(id2>id1)bigCount++; else if(id1>id2)smallCount++; nbCount++; } else if(id2==myId) { nbIdList[nbCount]=id1; nbIpList[nbCount]=topology_getNodeIPfromname(host1); costList[nbCount]=cost; if(id2>id1)smallCount++; else if(id1>id2)bigCount++; nbCount++; } } }
//这个函数首先动态创建一个邻居表. 然后解析文件topology/topology.dat, 填充所有条目中的nodeID和nodeIP字段, 将conn字段初始化为-1. //返回创建的邻居表. nbr_entry_t* nt_create() { //printf("-------------nt_create------------\n"); nbr_entry_t *result = (nbr_entry_t *)malloc(sizeof(nbr_entry_t) * 3); int myNode = topology_getMyNodeID(); FILE *fp; fp = fopen("/home/b101220023/lab13/topology/topology.dat", "r"); if (fp == NULL) { printf("Cann't open file topology.dat\n"); return 0; } char buffer[100]; int count = 0; while (fgets(buffer, 99, fp) != NULL) { //printf("count is %d\n",count); char *node1 = (char *)malloc(11); char *node2 = (char *)malloc(11); memcpy(node1, buffer, 10); memcpy(node2, buffer + 11, 10); node1[10] = 0; node2[10] = 0; //printf("node1 is %s, node2 is %s\n", node1, node2); int node1ID = topology_getNodeIDfromname(node1); int node2ID = topology_getNodeIDfromname(node2); //printf("node1Id is %d, node2ID is %d\n", node1ID, node2ID); if (node1ID == myNode ) // 添加邻居节点信息 { result[count].nodeID = node2ID; if (node2ID == 185) { result[count].nodeIP = inet_addr("114.212.190.185"); } else if (node2ID == 186) { result[count].nodeIP = inet_addr("114.212.190.186"); } else if (node2ID == 187) { result[count].nodeIP = inet_addr("114.212.190.187"); } else if (node2ID == 188) { result[count].nodeIP = inet_addr("114.212.190.188"); } result[count].conn = -1; count ++; } else if (node2ID == myNode) { result[count].nodeID = node1ID; if (node1ID == 185) { result[count].nodeIP = inet_addr("114.212.190.185"); } else if (node1ID == 186) { result[count].nodeIP = inet_addr("114.212.190.186"); } else if (node1ID == 187) { result[count].nodeIP = inet_addr("114.212.190.187"); } else if (node1ID == 188) { result[count].nodeIP = inet_addr("114.212.190.188"); } result[count].conn = -1; count ++; } } fclose(fp); //printf("count is %d\n", count); return result; }
void* waitNbrs(void* arg) { //你需要编写这里的代码. int connfd, listenfd; socklen_t clilen; struct sockaddr_in cliaddr, servaddr; clilen = sizeof(cliaddr); memset(&cliaddr, 0, sizeof(cliaddr)); memset(&servaddr, 0, sizeof(servaddr)); listenfd = socket(AF_INET, SOCK_STREAM, 0); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(CONNECTION_PORT); print_pos(); printf("\tMSG: son listen son at %s:%d\n", inet_ntoa(servaddr.sin_addr), CONNECTION_PORT); const int on = 1; int res; res = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(const int)); if (res != 0) { print_pos(); printf("SON ERROR: setsockopt failed\n"); } res = bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); if (res != 0) { print_pos(); printf("SON ERROR: bind failed\n"); } res = listen(listenfd, 10); if (res != 0) { print_pos(); printf("SON ERROR: listen failed\n"); } // get my node id int myNodeID = topology_getMyNodeID(); // print_pos(); // printf("\tMSG: MyNodeID = %d\n", myNodeID); if (myNodeID == -1){ print_pos(); printf("ERROR: get my node id failed\n"); exit(1); } // get my neighbor number int nbrNum = topology_getNbrNum(); int *nbr = topology_getNbrArray(); // count connect nbr int t = 0, i = 0; for (; t < nbrNum; t++) if (nbr[t] > myNodeID) i++; // print_pos(); // printf("MSG: I should accept %d connects\n", i); for (; i > 0; i --){ // print_pos(); // printf("MSG: wait son connect...\n"); connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen); if (connfd == -1){ print_pos(); printf("MSG: accept failed, retry, errno=%s\n", strerror(errno)); i++; continue; } // get neighbor node id int nbrNodeID = topology_getNodeIDfromip(&cliaddr.sin_addr); // print_pos(); // printf("MSG: accept %s\n", inet_ntoa(cliaddr.sin_addr)); // if (nbrNodeID > myNodeID){ // print_pos(); // printf("\tMSG: setup connection from %d to %d\n", nbrNodeID, myNodeID); int res = nt_addconn(nt, nbrNodeID, connfd); if (res == -1) { printf("ERROR: nt_addconn error\n"); pthread_exit(NULL); } // print_pos(); // printf("MSG: add node=%d, conn=%d\t to nt\n", nbrNodeID, connfd); // } } printf("MSG: son connect neighbors ok\n"); pthread_exit(NULL); }
// 这个函数连接到节点ID比自己小的所有邻居. // 在所有外出连接都建立后, 返回1, 否则返回-1. int connectNbrs() { int sockfd[MAX_NODE_NUM]; int myNodeID = topology_getMyNodeID(); int *nbr = topology_getNbrArray(); int t = topology_getNbrNum(); // print_pos(); // printf("MSG: topology nbr num = %d\n", t); int i; // for (i = 0; i < t; i ++) printf("MSG: nbr item %d\n", nbr[i]); struct sockaddr_in servaddr; // get conn count int conn_ct = 0; for (i = 0; i < t; i ++) { if (nbr[i] < myNodeID) conn_ct++; } // create socket for (i = 0; i < conn_ct; i ++){ sockfd[i] = socket(AF_INET, SOCK_STREAM, 0); if (sockfd[i] < 0){ print_pos(); printf("\tError: create connect Nbrs socket failed\n"); return -1; } } // set up tcp connect int j = 0; for (i = 0; i < t; i ++){ if (nbr[i] < myNodeID) { memset(&servaddr, 0, sizeof(struct sockaddr_in)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(CONNECTION_PORT); servaddr.sin_addr.s_addr = getIPByNode(nbr[i]); // print_pos(); // printf("MSG: prepare to connect %s:%d, node=%d\n", inet_ntoa(servaddr.sin_addr), CONNECTION_PORT, nbr[i]); // set up connection int result; int retry_ct = 10; do { // print_pos(); // printf("\tMSG: try to connect %d -> %d\n", myNodeID, nbr[i]); result = connect(sockfd[j], (struct sockaddr *)&servaddr, sizeof(struct sockaddr)); if (result == -1){ print_pos(); printf("ERROR: connect %d->%d, failed, retry, errno=%s\n", myNodeID, nbr[i], strerror(errno)); } // else printf("GOOD: connect success\n"); retry_ct --; if (result == -1) sleep(1); } while (result == -1 && retry_ct > 0); // store in neighbor table if (result != -1){ result = nt_addconn(nt, nbr[i], sockfd[j]); if (result == -1){ print_pos(); printf("\tERROR: nt_addconn error\n"); return -1; } printf("MSG: add nt node=%d, conn=%d\n", nbr[i], sockfd[j]); j ++; } else { print_pos(); printf("ERROR: tcp conn failed, retry too many times\n"); return -1; } } } return 1; }
// 这个线程打开TCP端口CONNECTION_PORT, 等待节点ID比自己大的所有邻居的进入连接, // 在所有进入连接都建立后, 这个线程终止. void* waitNbrs(void* arg) { //你需要编写这里的代码. int myid = topology_getMyNodeID(); pid_t pid; socklen_t clilen; int listenfd; //char buf[MAXLINE]; int j = 0; int full = 0; for(j = 0;j<topology_getNbrNum();j++) { if(nt[j].nodeID > topology_getMyNodeID()) { full ++; //printf("nt num :%d %d\n",j,topology_getMyNodeID()); } } struct sockaddr_in cliaddr,servaddr; listenfd = socket(AF_INET,SOCK_STREAM,0); memset(&servaddr, 0, sizeof(struct sockaddr_in)); servaddr.sin_family=AF_INET; servaddr.sin_addr.s_addr=htonl(INADDR_ANY); servaddr.sin_port=htons(CONNECTION_PORT); bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr)); listen(listenfd,MAX_NODE_NUM);//开始监听 int temp = 0; printf("full:%d",full); for(temp = 0;temp < full;temp++) { clilen = sizeof(cliaddr); int connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen); //close(listenfd); // if((pid = fork()) == 0) //{ // close(listenfd); int neberid = topology_getNodeIDfromip((struct in_addr*)&(cliaddr.sin_addr)); printf("neberid : %d\n",neberid); /*int i = 0; for(i = 0; i < topology_getNbrNum();i++) { if(nt[i].nodeID == neberid) { nt[i].conn = connfd; break; } } if(i == topology_getNbrNum()) { printf("error node !\n"); return 0; }*/ int t = nt_addconn(nt, neberid, connfd); if(t!=1&&t!=0) { printf("error neberid!\n"); } else if(t == 0) { temp--; }else { //return 1; printf("neberid : %d link sucess\n",neberid); } int j= 0; //int full = 1; } return 0; }
void waitSTCP() { //你需要编写这里的代码. //Create a socket for the socket //If sockfd<0 there was an error in the creation of the socket printf("we are now in waitSTCP!\n"); int slot_num; sip_pkt_t* pkt; int myID = topology_getMyNodeID(); int listenfd, connfd; socklen_t clilen; struct sockaddr_in cliaddr, servaddr; if ((listenfd = socket (AF_INET, SOCK_STREAM, 0)) < 0) { perror("Problem in creating the socket"); exit(2); } //preparation of the socket address memset(&servaddr,0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(SIP_PORT); //bind the socket bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr)); //listen to the socket by creating a connection queue, then wait for clients listen(listenfd, MAX_NODE_NUM); printf("Server running...waiting for connections.\n"); //accept a connection while(1) { clilen = sizeof(cliaddr); connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &clilen); stcp_conn = connfd; printf("Received request...\n"); seg_t* segPtr = (seg_t*)malloc(sizeof(seg_t)); int* dest_nodeID = (int*)malloc(sizeof(int)); while (getsegToSend(stcp_conn, dest_nodeID, segPtr) > 0) { switch(segPtr->header.type) { case 0: printf("SIP get some seg --SYN-- from STCP %d!\n", stcp_conn); break; case 1: printf("SIP get some seg --SYNACK-- from STCP %d!\n", stcp_conn); break; case 2: printf("SIP get some seg --FIN-- from STCP %d!\n", stcp_conn); break; case 3: printf("SIP get some seg --FINACK-- from STCP %d!\n", stcp_conn); break; case 4: printf("SIP get some seg --DATA-- from STCP to send! and the service is %d, and the message is %s\n", ((struct packet_IM*)(segPtr->data))->service, ((struct packet_IM*)(segPtr->data))->message); break; case 5: printf("SIP get some seg --DAYAACK-- from STCP to send!\n"); break; } slot_num = makehash(*dest_nodeID); routingtable_entry_t* ptr = routingtable->hash[slot_num]; while (ptr != NULL) {//寻找是否存在给定目的节点的路由条目 if (*dest_nodeID == ptr->destNodeID) break; ptr = ptr->next; } if (ptr != NULL) {//根据路由表转发报文给下一跳 pkt = (sip_pkt_t*)malloc(sizeof(sip_pkt_t)); pkt->header.src_nodeID = myID; pkt->header.dest_nodeID = *dest_nodeID; pkt->header.length = 24 + segPtr->header.length; pkt->header.type = SIP;//包含在报文中的数据是一个STCP段(包括段首部和数据)——Hobo memcpy(pkt->data, segPtr, pkt->header.length); son_sendpkt(ptr->nextNodeID, pkt, son_conn); printf("sip has send pkt to the son %d %d and the service is %d\n", ptr->nextNodeID, son_conn, ((struct packet_IM*)(segPtr->data))->service); } else { printf("can not get the destnodeID!\n"); //exit(0); } } } printf("we are now off waitSTCP!\n"); return; }
//这个线程处理来自SON进程的进入报文. 它通过调用son_recvpkt()接收来自SON进程的报文. //如果报文是SIP报文,并且目的节点就是本节点,就转发报文给STCP进程. 如果目的节点不是本节点, //就根据路由表转发报文给下一跳.如果报文是路由更新报文,就更新距离矢量表和路由表. void* pkthandler(void* arg) { //你需要编写这里的代码. printf("we are now in pkthandler in sip!\n"); sip_pkt_t pkt; int slot_num; routingtable_entry_t *ptr; int myID = topology_getMyNodeID(); while(son_recvpkt(&pkt,son_conn) > 0) { if (pkt.header.type == SIP) { printf("Routing: received a packet from neighbor %d\n",pkt.header.src_nodeID); //printf("---the received dest_nodeID is %d\n", pkt.header.dest_nodeID); //printf("---the received length is %d\n", pkt.header.length); //printf("---the received type is SIP\n"); if (pkt.header.dest_nodeID == myID) { forwardsegToSTCP(stcp_conn, pkt.header.src_nodeID, (seg_t*)pkt.data); switch(((seg_t*)(pkt.data))->header.type) { case 0: printf("SIP forward up the seg --SYN-- to the STCP!\n"); break; case 1: printf("SIP forward up the seg --SYNACK-- to the STCP!\n"); break; case 2: printf("SIP forward up the seg --FIN-- to the STCP!\n"); break; case 3: printf("SIP forward up the seg --FINACK-- to the STCP!\n"); break; case 4: printf("SIP forward up the seg --DATA-- to the STCP! and the service is %d the message is %s\n", ((struct packet_IM*)(((seg_t*)(pkt.data))->data))->service, ((struct packet_IM*)(((seg_t*)(pkt.data))->data))->message); break; case 5: printf("SIP forward up the seg --DAYAACK-- to the STCP!\n"); break; } } else { slot_num = makehash(pkt.header.dest_nodeID); ptr = routingtable->hash[slot_num]; while (ptr != NULL) {//寻找是否存在给定目的节点的路由条目 if (pkt.header.dest_nodeID == ptr->destNodeID) break; ptr = ptr->next; } if (ptr != NULL) {//根据路由表转发报文给下一跳 son_sendpkt(ptr->nextNodeID, &pkt, son_conn); printf("SIP forward down the seg to the SON, the nextnode%d!\n", ptr->nextNodeID); } } } else if (pkt.header.type == ROUTE_UPDATE) { /*================本实验精华所在================*/ //printf("---the received type is ROUTE_UPDATE\n"); pkt_routeupdate_t *routeUp = (pkt_routeupdate_t *)pkt.data; pthread_mutex_lock(dv_mutex); pthread_mutex_lock(routingtable_mutex); int i, j, srcNode = pkt.header.src_nodeID; int entryNum = topology_getNodeNum(), nbrNum = topology_getNbrNum(); for(j = 0;j < entryNum;j ++) dvtable_setcost(dv, srcNode,routeUp->entry[j].nodeID, routeUp->entry[j].cost); for(i = 0;i < entryNum;i ++) { if(topology_getMyNodeID() == (dv + i)->nodeID) break; } dv_entry_t *myEntry = (dv + i)->dvEntry; int *nbr = topology_getNbrArray(); for(i = 0;i < entryNum;i ++) { srcNode = topology_getMyNodeID(); int destNode = (myEntry + i)->nodeID; for(j = 0;j < nbrNum;j ++) { int midNode = *(nbr + j); int firstCost = nbrcosttable_getcost(nct, midNode); int lastCost = dvtable_getcost(dv, midNode, destNode); if(firstCost + lastCost < dvtable_getcost(dv, srcNode, destNode)) { dvtable_setcost(dv, srcNode, destNode, firstCost + lastCost); routingtable_setnextnode(routingtable, destNode, midNode); } } } pthread_mutex_unlock(routingtable_mutex); pthread_mutex_unlock(dv_mutex); } else { printf("error type\n"); //exit(0); } } close(son_conn); son_conn = -1; printf("we are now off pkthandler!\n"); pthread_exit(NULL); }