// 这个函数连接到节点ID比自己小的所有邻居. // 在所有外出连接都建立后, 返回1, 否则返回-1. int connectNbrs() { int mynode= topology_getMyNodeID(); int mynbrnum = topology_getNbrNum(); int *nbrlist = topology_getNbrArray(); int i=0; for(i=0; i<mynbrnum; i++) { if(nbrlist[i] < mynode) { int sockfd; struct sockaddr_in serv_addr; if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) <0) { perror("Error create socket!\n"); return -1; } memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = topology_getfromIDtoIP(nbrlist[i]); serv_addr.sin_port = htons(CONNECTION_PORT); if(connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr))<0) { perror("Error connect\n"); return -1; } nt_addconn(nt, nbrlist[i], sockfd); } } return 1; }
//This function creates a routing table dynamically. //All the entries in the table are initialized to NULL pointers. //Then for all the neighbors with a direct link, create a routing entry using the neighbor itself as the //next hop node, and insert this routing entry into the routing table. //The dynamically created routing table structure is returned. routingtable_t* routingtable_create() { routingtable_t *routingTable = malloc(sizeof(routingtable_entry_t *)*MAX_ROUTINGTABLE_SLOTS); memset(routingTable, 0, sizeof(routingtable_entry_t *)*MAX_ROUTINGTABLE_SLOTS); //initialize all hash entries to NULL for (int i = 0; i < MAX_ROUTINGTABLE_SLOTS; i++) { routingTable->hash[i] = NULL; } //initialize neighbors int* nbrArray = topology_getNbrArray(); int numNbrs = topology_getNbrNum(); for (int j = 0; j < numNbrs; j++){ routingtable_entry_t *temp = malloc(sizeof(routingtable_entry_t)); temp->destNodeID = nbrArray[j]; temp->nextNodeID = nbrArray[j]; temp->next = NULL; int tempHash = makehash(nbrArray[j]); if (routingTable->hash[tempHash] == NULL) { routingTable->hash[tempHash] = temp; } else { routingtable_entry_t *tempEntry = routingTable->hash[tempHash]; while (tempEntry->next != NULL) { tempEntry = tempEntry->next; } tempEntry->next = temp; } } //routingtable_print(routingTable); free(nbrArray); return routingTable; }
//这个函数动态创建距离矢量表. //距离矢量表包含n+1个条目, 其中n是这个节点的邻居数,剩下1个是这个节点本身. //距离矢量表中的每个条目是一个dv_t结构,它包含一个源节点ID和一个有N个dv_entry_t结构的数组, 其中N是重叠网络中节点总数. //每个dv_entry_t包含一个目的节点地址和从该源节点到该目的节点的链路代价. //距离矢量表也在这个函数中初始化.从这个节点到其邻居的链路代价使用提取自topology.dat文件中的直接链路代价初始化. //其他链路代价被初始化为INFINITE_COST. //该函数返回动态创建的距离矢量表. dv_t* dvtable_create() { int nbr_count = topology_getNbrNum(); int * nbr_array = topology_getNbrArray(); int node_count = topology_getNodeNum(); int * node_array = topology_getNodeArray(); dv_t * dvtable = (dv_t *)malloc( sizeof(dv_t) * (nbr_count + 1) ); memset(dvtable, 0, sizeof(dv_t) * (nbr_count+1) ); int i, j; // the first dv_t has nodeID of itself. dvtable[0].nodeID = topology_getMyNodeID(); dvtable[0].dvEntry = (dv_entry_t *)malloc(sizeof(dv_entry_t)*(node_count)); memset(dvtable[0].dvEntry, 0, sizeof(dv_entry_t)*(node_count)); for (j = 0; j < node_count; ++j) { dvtable[0].dvEntry[j].nodeID = node_array[j]; dvtable[0].dvEntry[j].cost = topology_getCost(dvtable[0].nodeID, node_array[j]); if (dvtable[0].nodeID == dvtable[0].dvEntry[j].nodeID) dvtable[0].dvEntry[j].cost = 0; } for (i = 1; i < nbr_count+1; ++i) { dvtable[i].nodeID = nbr_array[i-1]; dvtable[i].dvEntry = (dv_entry_t *)malloc( sizeof(dv_entry_t)*node_count); memset(dvtable[i].dvEntry, 0, sizeof(dv_entry_t)*node_count); for (j = 0; j < node_count; ++j) { dvtable[i].dvEntry[j].nodeID = node_array[j]; dvtable[i].dvEntry[j].cost = INFINITE_COST; } } return dvtable; }
//这个函数首先动态创建一个邻居表. 然后解析文件topology/topology.dat, 填充所有条目中的nodeID和nodeIP字段, 将conn字段初始化为-1. //返回创建的邻居表. nbr_entry_t* nt_create() { int i; int num_nbr = topology_getNbrNum();//获取邻居节点数 nbr_entry_t* nt = (nbr_entry_t*)malloc(num_nbr * sizeof(struct neighborentry));//创建邻居表空间 int* temp = topology_getNbrArray();//获取邻居节点ID数组 for (i = 0; i < num_nbr; i++) { nt[i].nodeID = temp[i];///////////////// nt[i].nodeIP = (0x72D4BE << 8) + temp[i]; nt[i].conn = -1; } return nt; }
//这个函数动态创建距离矢量表. //距离矢量表包含n+1个条目, 其中n是这个节点的邻居数,剩下1个是这个节点本身. //距离矢量表中的每个条目是一个dv_t结构,它包含一个源节点ID和一个有N个dv_entry_t结构的数组, 其中N是重叠网络中节点总数. //每个dv_entry_t包含一个目的节点地址和从该源节点到该目的节点的链路代价. //距离矢量表也在这个函数中初始化.从这个节点到其邻居的链路代价使用提取自topology.dat文件中的直接链路代价初始化. //其他链路代价被初始化为INFINITE_COST. //该函数返回动态创建的距离矢量表. dv_t* dvtable_create() { getTopoData(); nbn=topology_getNbrNum(); int *nbList=topology_getNbrArray(); int *costList=topology_getNbrCost(); alln=topology_getNodeNum(); int *allList=topology_getNodeArray(); dv_t *dvList=malloc((nbn+1)*sizeof(dv_t)); if(dvList==NULL)exit(-1); int i=0; //init nerghbor for(;i<nbn;i++) { dvList[i].nodeID=nbList[i]; dvList[i].dvEntry=malloc(alln*sizeof(dv_entry_t)); int j=0; for(;j<alln;j++) { dvList[i].dvEntry[j].nodeID=allList[j]; dvList[i].dvEntry[j].cost=INFINITE_COST; } } //init this node dvList[nbn].nodeID=topology_getMyNodeID(); dvList[nbn].dvEntry=malloc(alln*sizeof(dv_entry_t)); for(i=0;i<alln;i++) { dvList[nbn].dvEntry[i].nodeID=allList[i]; if(allList[i]==dvList[nbn].nodeID) { dvList[nbn].dvEntry[i].cost=0; continue; } int j=0; for(;j<nbn;j++) { if(allList[i]==nbList[j]) { dvList[nbn].dvEntry[i].cost=costList[j]; break; } } if(j==nbn) dvList[nbn].dvEntry[i].cost=INFINITE_COST; } return dvList; }
//这个函数动态创建路由表.表中的所有条目都被初始化为NULL指针. //然后对有直接链路的邻居,使用邻居本身作为下一跳节点创建路由条目,并插入到路由表中. //该函数返回动态创建的路由表结构. routingtable_t* routingtable_create() { routingtable_t * my_route = (routingtable_t *)malloc(sizeof(routingtable_t)); int i = 0; for(i=0; i<MAX_ROUTINGTABLE_SLOTS; i++) { my_route->hash[i] = NULL; } int nbrnum = topology_getNbrNum(); int *nbrlist = topology_getNbrArray(); int j; for( j=0; j<nbrnum; j++) { routingtable_setnextnode(my_route, nbrlist[j], nbrlist[j]); } return my_route; }
//这个函数动态创建邻居代价表并使用邻居节点ID和直接链路代价初始化该表. //邻居的节点ID和直接链路代价提取自文件topology.dat. nbr_cost_entry_t* nbrcosttable_create() { int nbrnum = topology_getNbrNum(); nbr_cost_entry_t *nbr_table = (nbr_cost_entry_t*)malloc(sizeof(nbr_cost_entry_t)); int* nbrlist = topology_getNbrArray(); int mynode = topology_getMyNodeID(); int i = 0; for(i = 0; i<nbrnum; i++) { nbr_table[i].nodeID = nbrlist[i]; nbr_table[i].cost = topology_getCost(mynode, nbrlist[i]); nbr_table[i].flag = 0; pthread_mutex_init(&nbr_table[i].flag_mutex, NULL); } return nbr_table; }
//这个函数首先动态创建一个邻居表. 然后解析文件topology/topology.dat, 填充所有条目中的nodeID和nodeIP字段, 将conn字段初始化为-1. //返回创建的邻居表. nbr_entry_t* nt_create() { int entry_num = topology_getNbrNum(); nbr_entry_t *neighbor_table = (nbr_entry_t *)malloc(sizeof(nbr_entry_t) * nbr_entry_num); nbr_entry_t *neighbor_entry = neighbor_table; int *node_id_array = topology_getNbrArray(); int i; for (i = 0; i < entry_num; i++) { neighbor_entry -> nodeID = node_id_array[i]; neighbor_entry -> nodeIP = htonl(topology_getLocalIP() | node_id_array[i]); neighbor_entry -> conn = -1; neighbor_entry ++; } neighbor_entry = NULL; free(node_id_array); return neighbor_table; }
//这个函数动态创建路由表.表中的所有条目都被初始化为NULL指针. //然后对有直接链路的邻居,使用邻居本身作为下一跳节点创建路由条目,并插入到路由表中. //该函数返回动态创建的路由表结构. routingtable_t* routingtable_create() { routingtable_t *route_table = (routingtable_t *)malloc(sizeof (routingtable_t)); int i = 0; for(i = 0; i < MAX_ROUTINGTABLE_SLOTS; i++) route_table->hash[i] = NULL; int nbrnum = topology_getNbrNum(); int *nbrArray = topology_getNbrArray(); for(i = 0; i < nbrnum; i++){ int nextNodeID = nbrArray[i]; int index = makehash(nextNodeID); routingtable_entry_t *temp = route_table->hash[index]; routingtable_entry_t *new_entry = (routingtable_entry_t *)malloc(sizeof(routingtable_entry_t)); new_entry->destNodeID = nextNodeID; new_entry->nextNodeID = nextNodeID; new_entry->next = temp; route_table->hash[index] = new_entry; } return route_table; }
//这个函数首先动态创建一个邻居表. 然后解析文件topology/topology.dat, 填充所有条目中的nodeID和nodeIP字段, 将conn字段初始化为-1. //返回创建的邻居表. nbr_entry_t *nt_create() { int this_id = topology_getMyNodeID(); in_addr_t this_ip = topology_getIP(); int nr_nbrs = topology_getNbrNum(); int *nbrs = topology_getNbrArray(); log("%d has %d neighbors", this_id, nr_nbrs); nbr_entry_t *table = calloc((size_t)nbrs, sizeof(*table)); for (int i = 0; i < nr_nbrs; i++) { log("create nbr table entry for %d", nbrs[i]); table[i].conn = -1; table[i].nodeID = nbrs[i]; table[i].nodeIP = (this_ip & (~0xFF)) | nbrs[i]; } free(nbrs); return table; }
// 这个线程打开TCP端口CONNECTION_PORT, 等待节点ID比自己大的所有邻居的进入连接, // 在所有进入连接都建立后, 这个线程终止. void* waitNbrs(void* arg) { int connfd; int mynode= topology_getMyNodeID(); int mynbrnum = topology_getNbrNum(); int *nbrlist = topology_getNbrArray(); int listenq=0; int i = 0; for(i=0; i<mynbrnum; i++) { if(nbrlist[i]>mynode) listenq++; } socklen_t clilen; struct sockaddr_in cli_addr, serv_addr; if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("Error create socket\n"); exit(-1); } const int one = 1; //port可以立即重新使用 setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one) ); memset(&serv_addr,0,sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(CONNECTION_PORT); if(bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr))<0) { perror("Error bind\n"); exit(-1); } listen(listenfd, MAX_NODE_NUM); clilen = sizeof(cli_addr); for(i=0; i<listenq; i++) { connfd = accept(listenfd, (struct sockaddr *)&cli_addr, &clilen); int node = topology_getNodeIDfromip(&cli_addr.sin_addr); if(nt_addconn(nt, node, connfd) == -1) { printf("Error add!\n"); } printf("Add Node: %d\n", node); } return 0; }
//这个线程处理来自SON进程的进入报文. 它通过调用son_recvpkt()接收来自SON进程的报文. //如果报文是SIP报文,并且目的节点就是本节点,就转发报文给STCP进程. 如果目的节点不是本节点, //就根据路由表转发报文给下一跳.如果报文是路由更新报文,就更新距离矢量表和路由表. void* pkthandler(void* arg) { sip_pkt_t pkt; int myNodeID = topology_getMyNodeID(); int nbr_num = topology_getNbrNum(); int node_num = topology_getNodeNum(); while(son_recvpkt(&pkt,son_conn)>0) { // printf("Routing: received a packet from neighbor %d\n",pkt.header.src_nodeID); switch(pkt.header.type){ case ROUTE_UPDATE: pthread_mutex_lock(dv_mutex); pthread_mutex_lock(routingtable_mutex); pkt_routeupdate_t *routemsg = (pkt_routeupdate_t *)pkt.data; int i, j, srcNode = pkt.header.src_nodeID; printf("receive ROUTE UPDATE MESSAGE FROM NODE %d\n", srcNode); for(j = 0; j < routemsg->entryNum; j ++) dvtable_setcost(dv, srcNode, routemsg->entry[j].nodeID, routemsg->entry[j].cost); for(i = 0;i < nbr_num + 1;i ++) { if(myNodeID == dv[i].nodeID) break; } dv_entry_t *myEntry = dv[i].dvEntry; int *nbr = topology_getNbrArray(); for(i = 0; i < node_num; i ++) { int destNode = myEntry[i].nodeID; for(j = 0;j < nbr_num;j ++) { int viaNode = nbr[j]; int firstCost = nbrcosttable_getcost(nct, viaNode); int lastCost = dvtable_getcost(dv, viaNode, destNode); if(firstCost + lastCost < dvtable_getcost(dv, myNodeID, destNode)) { printf("now update routing table\n"); printf("to destNode %d via nextNode %d \n", destNode, viaNode); dvtable_setcost(dv, myNodeID, destNode, firstCost + lastCost); routingtable_setnextnode(routingtable, destNode, viaNode); } } } pthread_mutex_unlock(routingtable_mutex); pthread_mutex_unlock(dv_mutex); break; case SIP: if(pkt.header.dest_nodeID == topology_getMyNodeID()){ seg_t seg_data; memcpy(&seg_data, pkt.data, sizeof(seg_t)); printf("RECEIVE PKT, destNode is me "); if(forwardsegToSTCP(stcp_conn, pkt.header.src_nodeID, &seg_data) == -1) printf("failed forwarding the seg to local STCP \n"); else printf("FORWARD the seg to local STCP \n"); } else{ pthread_mutex_lock(routingtable_mutex); int nextNodeID = routingtable_getnextnode(routingtable, pkt.header.dest_nodeID); pthread_mutex_unlock(routingtable_mutex); if(son_sendpkt(nextNodeID, &pkt, son_conn) == -1) printf("can't send pkt to son \n"); else printf("RECEIVE PKT but DESTNODE is %d SO TRANSMIT it to nextNodeID %d\n", pkt.header.dest_nodeID, nextNodeID); } break; } } pthread_exit(NULL); }
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; }
//这个线程处理来自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); }