//每个listen_to_neighbor线程持续接收来自一个邻居的报文. 它将接收到的报文转发给SIP进程. //所有的listen_to_neighbor线程都是在到邻居的TCP连接全部建立之后启动的. void* listen_to_neighbor(void* arg) { int i = *(int *)arg; int conn = nt[i].conn; sip_pkt_t* sip_pkt; while(1) { sip_pkt = (sip_pkt_t*)malloc(sizeof(sip_pkt_t)); memset(sip_pkt, 0, sizeof(sip_pkt_t)); if(recvpkt(sip_pkt, conn) > 0) { if(sip_pkt->header.type == SIP ) { printf("receive stcp packet from node %d\n", sip_pkt->header.src_nodeID); } forwardpktToSIP(sip_pkt, sip_conn); } else { //nt[i].conn = -1; wait for next connection close(conn); socklen_t clilen; struct sockaddr_in cli_addr; clilen = sizeof(cli_addr); conn = accept(listenfd, (struct sockaddr*)&cli_addr, &clilen); int node = topology_getNodeIDfromip(&cli_addr.sin_addr); nt_addconn(nt, node, conn); } free(sip_pkt); } }
//每个listen_to_neighbor线程持续接收来自一个邻居的报文. 它将接收到的报文转发给SIP进程. //所有的listen_to_neighbor线程都是在到邻居的TCP连接全部建立之后启动的. void* listen_to_neighbor(void* arg) { while(1) { sip_pkt_t* pkt = (sip_pkt_t*)malloc(sizeof(sip_pkt_t)); memset(pkt,0,sizeof(sip_pkt_t)); if(recvpkt(pkt, nt[*((int *)arg)].conn) != -1) forwardpktToSIP(pkt,sip_conn); else { //sip_pkt_t* pkt = (sip_pkt_t*)malloc(sizeof(sip_pkt_t)); memset(pkt,0,sizeof(sip_pkt_t)); pkt->header.src_nodeID = topology_getMyNodeID(); //printf("send neb my iD : %d\n",pkt->header.src_nodeID); pkt->header.dest_nodeID = nt[*((int *)arg)].nodeID; pkt->header.length = 0; pkt->header.type = SLEEP; forwardpktToSIP(pkt,sip_conn); nt[*((int *)arg)].conn = -1; return 0; } printf("send packet to IP\n"); } return 0; }
//每个listen_to_neighbor线程持续接收来自一个邻居的报文. 它将接收到的报文转发给SIP进程. //所有的listen_to_neighbor线程都是在到邻居的TCP连接全部建立之后启动的. void* listen_to_neighbor(void* arg) { int index = *(int *)arg; // printf("MSG: listen to neighbor node=%d\n", nt[index].nodeID); sip_pkt_t tmp; if (nt[index].conn == -1) { print_pos(); printf("ERROR: connect not set for node %d\n", nt[index].nodeID); pthread_exit(NULL); } while (1) { memset(&tmp, 0, sizeof(sip_pkt_t)); // recv a pkt from son // print_pos(); // printf("MSG: prepare to recvpkt from socket=%d\n", nt[index].conn); int result; result = recvpkt(&tmp, nt[index].conn); if (result == -1){ print_pos(); printf("ERROR: recvpkt from neighbor node=%d socket=%d failed\n", nt[index].nodeID, nt[index].conn); sleep(1); } // else printf("MSG: recvpkt sip_pkt_t ok, send to sip...\n"); // forward the pkt to sip result = forwardpktToSIP(&tmp, sip_conn); if (result == -1){ print_pos(); printf("ERROR: forward pkt to sip failed\n"); } // else printf("MSG: send to sip ok\n"); } pthread_exit(NULL); }
// Reads a value from the given network socket. // Accepts: file descriptor, caller-owned buffer, spot for the (newly) allocated buffer's length // Returns: whether a file was received reasonably bool hashhash::recvfile(int sfd, char **data, size_t *dlen) { size_t cap = MAX_PACKET_LEN-3+1; *data = (char *)malloc(cap); *dlen = 0; uint16_t llen; do { if(cap-*dlen <= MAX_PACKET_LEN-3) { // The buffer won't fit the next packet! char *buf = (char*)malloc(cap*2); memcpy(buf, *data, cap); free(*data); *data = buf; cap *= 2; } char *line; if(!recvpkt(sfd, OPC_STF, &line, NULL, &llen, false)) return false; // bad shit happened memcpy(*data+*dlen, line, llen); free(line); *dlen += llen; } while(llen); (*data)[*dlen] = '\0'; return true; }
//每个listen_to_neighbor线程持续接收来自一个邻居的报文. 它将接收到的报文转发给SIP进程. //所有的listen_to_neighbor线程都是在到邻居的TCP连接全部建立之后启动的. void* listen_to_neighbor(void* arg) { sip_pkt_t* pkt = (sip_pkt_t *)malloc(sizeof(sip_pkt_t)); while(1){ memset(pkt, 0, sizeof(sip_pkt_t)); if(recvpkt(pkt,nt[*(int *)arg].conn) > 0) forwardpktToSIP(pkt, sip_conn); else pthread_exit(NULL); } }
//每个listen_to_neighbor线程持续接收来自一个邻居的报文. 它将接收到的报文转发给SIP进程. //所有的listen_to_neighbor线程都是在到邻居的TCP连接全部建立之后启动的. void* listen_to_neighbor(void* arg) { //你需要编写这里的代码. int now=(*(int*)arg); sip_pkt_t* data=malloc(sizeof(sip_pkt_t)); memset(data,0,sizeof(sip_pkt_t)); while (1){ if (recvpkt(data,nt[now].conn)<0) { close(nt[now].conn); //forwardpktToSIP(build_failpkt(nt[now].nodeID),sip_conn); break; } forwardpktToSIP(data,sip_conn); } free(data); }
//每个listen_to_neighbor线程持续接收来自一个邻居的报文. 它将接收到的报文转发给SIP进程. //所有的listen_to_neighbor线程都是在到邻居的TCP连接全部建立之后启动的. void* listen_to_neighbor(void* arg) { nbr_entry_t currNbr = nt[*(int *)arg]; int conn = currNbr.conn; sip_pkt_t pkt; while(1){ if (recvpkt(&pkt,conn) == 1){ printf("recv a pkt from nbr %d\n",currNbr.nodeID); if(forwardpktToSIP(&pkt,sip_conn) < 0) printf("Error in send pkt to SIP\n"); } else { printf("Error when try to recvpkt from neighbor\n"); printf("connect lost, exit\n"); close(nt[*(int *)arg].conn); nt[*(int *)arg].conn = -1; break; } } printf("Error in recvpkt\n"); return 0; }
void yield(int block) { /* Called by the main thread to indicate willingness to relinquish * control. Corresponds to a "label". If block is NULL, yield() will * return immediately if there is no work to be done (no pending * packets). Otherwise, yield() will block until the next packet * arrives. */ int flag = 0, r; packet_t pack; l: r = recvpkt(g.sockfd, &pack, block); if (r > 0) handle_message(&pack); else if (r < 0) { /* Retry connection */ close(g.sockfd); client_connect(); goto l; } }
/* The heart of (S)NTP, exchange NTP packets and compute values to correct the local clock */ int on_wire ( struct addrinfo *host, struct addrinfo *bcast ) { char addr_buf[INET6_ADDRSTRLEN]; register int try; SOCKET sock; struct key *pkt_key = NULL; int key_id = 0; struct timeval tv_xmt; struct pkt x_pkt; int error, rpktl, handle_pkt_res; if (ENABLED_OPT(AUTHENTICATION)) { key_id = (int) atol(OPT_ARG(AUTHENTICATION)); get_key(key_id, &pkt_key); } for (try=0; try<5; try++) { memset(&r_pkt, 0, sizeof rbuf); error = GETTIMEOFDAY(&tv_xmt, (struct timezone *)NULL); tv_xmt.tv_sec += JAN_1970; #ifdef DEBUG printf("sntp on_wire: Current time sec: %i msec: %i\n", (unsigned int) tv_xmt.tv_sec, (unsigned int) tv_xmt.tv_usec); #endif if (bcast) { create_socket(&sock, (sockaddr_u *)bcast->ai_addr); rpktl = recv_bcst_pkt(sock, &r_pkt, sizeof rbuf, (sockaddr_u *)bcast->ai_addr); closesocket(sock); } else { int pkt_len = generate_pkt(&x_pkt, &tv_xmt, key_id, pkt_key); create_socket(&sock, (sockaddr_u *)host->ai_addr); sendpkt(sock, (sockaddr_u *)host->ai_addr, &x_pkt, pkt_len); rpktl = recvpkt(sock, &r_pkt, sizeof rbuf, &x_pkt); closesocket(sock); } handle_pkt_res = handle_pkt(rpktl, &r_pkt, host); if (handle_pkt_res < 1) return handle_pkt_res; } getnameinfo(host->ai_addr, host->ai_addrlen, addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST); msyslog(LOG_DEBUG, "Received no useable packet from %s!", addr_buf); return -1; } /* Compute the 8 bits for li_vn_mode */ void set_li_vn_mode ( struct pkt *spkt, char leap, char version, char mode ) { if (leap > 3) { msyslog(LOG_DEBUG, "set_li_vn_mode: leap > 3 using max. 3"); leap = 3; } if (mode > 7) { msyslog(LOG_DEBUG, "set_li_vn_mode: mode > 7, using client mode 3"); mode = 3; } spkt->li_vn_mode = leap << 6; spkt->li_vn_mode |= version << 3; spkt->li_vn_mode |= mode; } /* set_time corrects the local clock by offset with either settimeofday() or by default * with adjtime()/adjusttimeofday(). */ int set_time( double offset ) { struct timeval tp; if (ENABLED_OPT(SETTOD)) { GETTIMEOFDAY(&tp, NULL); tp.tv_sec += (long)offset; tp.tv_usec += 1e6 * (offset - (long)offset); NORMALIZE_TIMEVAL(tp); if (SETTIMEOFDAY(&tp, NULL) < 0) { msyslog(LOG_ERR, "Time not set: settimeofday(): %m"); return -1; } return 0; } tp.tv_sec = (long)offset; tp.tv_usec = 1e6 * (offset - (long)offset); NORMALIZE_TIMEVAL(tp); if (ADJTIMEOFDAY(&tp, NULL) < 0) { msyslog(LOG_ERR, "Time not set: adjtime(): %m"); return -1; } return 0; }
main(int argc, char *argv[]) { setbuf(stdout, NULL); int sock; // check usage if (argc != 4) { fprintf(stderr, "usage : %s <username> <server_ip_address> <5945>\n", argv[0]); exit(1); } // get hooked on to the server sock = hooktoserver(argv[1], argv[2], atoi(argv[3])); if (sock == -1) exit(1); fflush(stdout); // Initialize FDs to zero. // Assign Input FD to client Fds. // Assign socked FD to client Fds. fd_set clientfds, tempfds; FD_ZERO(&clientfds); FD_ZERO(&tempfds); FD_SET(sock, &clientfds); FD_SET(0, &clientfds); while (1) { // Use tempfds as it will be overwritten on select call // We want clientfds to keep track of all connected fds. tempfds = clientfds; if (select(FD_SETSIZE, &tempfds, NULL, NULL, NULL) == -1) { perror("select"); exit(4); } // For every fd in the list, if the fd is set, check if // that is socket fd. If so, then it means that it we // received some message from server. It can be a message // from different client or server death. Also if the fd // is 0, it means there is some input from the user. // Read that input and send it to the server. int fd; for (fd = 0; fd < FD_SETSIZE; fd++) { if (FD_ISSET(fd,&tempfds)) { if (fd == sock) { Packet *pkt; pkt = recvpkt(sock); if (!pkt) { // server killed, exit fprintf(stderr, "Server closed the connection.\n"); exit(1); } // display the text if (pkt->type == EMAIL_MSG_TO_CLIENT) { printf("New email received !\n>> %s\n", pkt->text); }else if(pkt->type == WELCOME_MSG){ // Received welcome message. Print it. printf(">> %s\n", pkt->text); // Send username to client. char msg[MAXMSGLEN]; strcpy(msg, argv[1]); // fprintf(stderr, "user: %s", msg); sendpkt(sock, USER_NAME, strlen(msg) + 1, msg); }else if(pkt->type == SERVER_ERROR) { printf(">> %s\n", pkt->text); } else{ fprintf(stderr, "error: unexpected reply from server\n"); exit(1); } // free the message freepkt(pkt); } if (fd == 0) { char msg[MAXMSGLEN]; if (!fgets(msg, MAXMSGLEN, stdin)) exit(0); if (strncmp(msg, QUIT_STRING, strlen(QUIT_STRING)) == 0) { sendpkt(sock, CLOSE_CON, 0, NULL); break; } char * pch1, *pch2, *user, *ipaddr; pch1 = strstr(msg, " "); pch2 = strstr(msg, "@"); if (pch1 == NULL || pch2 == NULL) { fprintf(stderr, "error: invalid e-mail format.\nsyntax: <recp_user>@<ip_addr> <mesg>\n"); break; } if (pch1 < pch2) { fprintf(stderr, "error: user name cannot contain spaces.\n"); fprintf(stderr, "error: invalid e-mail format.\nsyntax: <recp_user>@<ip_addr> <mesg>\n"); break; } user = (char *) malloc((strlen(msg) - strlen(pch2) + 1)*sizeof(char)); strncpy(user, msg, (strlen(msg) - strlen(pch2))*sizeof(char)); user[strlen(msg) - strlen(pch2)] = '\0'; // fprintf(stderr, "client: user: %s", user); if(strcmp(user,"") == 0) { fprintf(stderr, "error: no username entered.\n"); free(user); break; } ipaddr = (char *) malloc( (strlen(pch2) - strlen(pch1))* sizeof(char)); strncpy(ipaddr, msg + strlen(user) + 1, (strlen(pch2) - strlen(pch1) - 1) * sizeof(char)); ipaddr[strlen(pch2) - strlen(pch1) - 1] = '\0'; // fprintf(stderr, "server: ip: %s", ipaddr); struct sockaddr_in sa; int result = inet_pton(AF_INET, ipaddr, &(sa.sin_addr)); if(result == 0){ fprintf(stderr, "error: invalid ip-address format.\nsyntax: <recp_user>@<ip_addr> <mesg>\n"); free(user); free(ipaddr); break; } char * mailmsg; mailmsg = (char *) malloc(strlen(pch1) * sizeof(char)); strncpy(mailmsg, msg + strlen(user) + strlen(ipaddr) + 2, (strlen(pch1) - 1) * sizeof(char)); mailmsg[strlen(pch1)-1] = '\0'; // It is okay to have empty body in the email message. if(strlen(mailmsg) > 80) { fprintf(stderr, "error: mail message length can be atmost 80 characters.\n"); free(user); free(ipaddr); free(mailmsg); break; } // fprintf(stderr, "server: mailmsg: %s", mailmsg); free(user); free(ipaddr); free(mailmsg); msg[strlen(msg) - 1] = '\0'; sendpkt(sock, EMAIL_MSG_TO_SERVER, strlen(msg) + 1, msg); } } } } }
/** Non blocking receive frame function. Uses RX buffer and index to combine * read frame with transmitted frame. To compensate for received frames that * are out-of-order all frames are stored in their respective indexed buffer. * If a frame was placed in the buffer previously, the function retreives it * from that buffer index without calling ec_recvpkt. If the requested index * is not already in the buffer it calls ec_recvpkt to fetch it. There are * three options now, 1 no frame read, so exit. 2 frame read but other * than requested index, store in buffer and exit. 3 frame read with matching * index, store in buffer, set completed flag in buffer status and exit. * * @param[in] port = port context struct * @param[in] idx = requested index of frame * @param[in] stacknumber = 0=primary 1=secondary stack * @return Workcounter if a frame is found with corresponding index, otherwise * EC_NOFRAME or EC_OTHERFRAME. */ int ecx_portt::inframe(int idx, int stacknumber) { ec_stackT *stack = (stacknumber == 0)? &(this->stack): &(this->redport->stack); int rval = EC_NOFRAME; ec_bufT *rxbuf = &(*stack->rxbuf)[idx]; /* check if requested index is already in buffer ? */ if ((idx < EC_MAXBUF) && ((*stack->rxbufstat)[idx] == EC_BUF_RCVD)) { /* return WKC */ rval = rxbuf->retreive(); /* mark as completed */ (*stack->rxbufstat)[idx] = EC_BUF_COMPLETE; } else { EnterCriticalSection(&(this->rx_mutex)); /* non blocking call to retrieve frame from socket */ if (recvpkt(stacknumber)) { rval = EC_OTHERFRAME; EtherNetHeader *ehp = stack->tempbuf->getEtherNetHeader(); /* check if it is an EtherCAT frame */ if (ehp->isEtherCATFrame()) { EC_Header *ecp = stack->tempbuf->getECATHeader(); uint8 idxf = ecp->getIndex(); /* found index equals reqested index ? */ if (idxf == idx) { /* yes, put it in the buffer array (strip ethernet header) */ memcpy(rxbuf, ecp, (*stack->txbuflength)[idx] - sizeof(EtherNetHeader)); /* return WKC */ uint16 l = ecp->getElength(); rval = rxbuf->getWorkCounterFromTempBuf(l); /* mark as completed */ (*stack->rxbufstat)[idx] = EC_BUF_COMPLETE; /* store MAC source word 1 for redundant routing info */ (*stack->rxsa)[idx] = ntohs(ehp->sa1); } /* check if index exist and someone is waiting for it */ else if(idxf < EC_MAXBUF && (*stack->rxbufstat)[idxf] == EC_BUF_TX) { rxbuf = &(*stack->rxbuf)[idxf]; /* put it in the buffer array (strip ethernet header) */ memcpy(rxbuf, ecp, (*stack->txbuflength)[idxf] - sizeof(EtherNetHeader)); /* mark as received */ (*stack->rxbufstat)[idxf] = EC_BUF_RCVD; (*stack->rxsa)[idxf] = ntohs(ehp->sa1); } else { /* strange things happend */ } } } LeaveCriticalSection(&(this->rx_mutex)); } /* WKC if mathing frame found */ return rval; }
/* try to join a group */ int joinagroup(int sock) { Packet * pkt; char bufr[MAXPKTLEN]; char * bufrptr; int bufrlen; char * gname; char * mname; /* send a list group request */ sendpkt(sock, LIST_GROUPS, 0, NULL); /* recv a list group reply */ pkt = recvpkt(sock); if (!pkt) { fprintf(stderr, "error: server died\n"); exit(1); } if (pkt->type != LIST_GROUPS) { fprintf(stderr, "error: unexpected reply from server\n"); exit(1); } /* display groups */ showgroups(pkt->lent, pkt->text); /* read in group name */ printf("which group? "); fgets(bufr, MAXPKTLEN, stdin); bufr[strlen(bufr)-1] = '\0'; /* may want to quit */ if (strcmp(bufr, "") == 0 || strncmp(bufr, QUIT_STRING, strlen(QUIT_STRING)) == 0) { close(sock); exit(0); } gname = strdup(bufr); /* read in member name */ printf("what nickname? "); fgets(bufr, MAXPKTLEN, stdin); bufr[strlen(bufr)-1] = '\0'; /* may want to quit */ if (strcmp(bufr, "") == 0 || strncmp(bufr, QUIT_STRING, strlen(QUIT_STRING)) == 0) { close(sock); exit(0); } mname = strdup(bufr); /* send a join group message */ bufrptr = bufr; strcpy(bufrptr, gname); bufrptr += strlen(bufrptr) + 1; strcpy(bufrptr, mname); bufrptr += strlen(bufrptr) + 1; bufrlen = bufrptr - bufr; sendpkt(sock, JOIN_GROUP, bufrlen, bufr); /* read the reply */ pkt = recvpkt(sock); if (!pkt) { fprintf(stderr, "error: server died\n"); exit(1); } if (pkt->type != JOIN_ACCEPTED && pkt->type != JOIN_REJECTED) { fprintf(stderr, "error: unexpected reply from server\n"); exit(1); } /* if rejected display the reason */ if (pkt->type == JOIN_REJECTED) { printf("admin: %s\n", pkt->text); free(gname); free(mname); return(0); } else { printf("admin: joined '%s' as '%s'\n", gname, mname); free(gname); free(mname); return(1); } }
/*--------------------------------------------------------------------*/ main(int argc, char *argv[]) { int sock; /* check usage */ if (argc != 1) { fprintf(stderr, "usage : %s\n", argv[0]); exit(1); } /* get hooked on to the server */ sock = hooktoserver(); if (sock == -1) exit(1); /* keep mingling */ while (1) { /* try to join a group */ if (!joinagroup(sock)) continue; /* joined some group. keep chatting */ while (1) { /* FILL HERE use select() to watch simulataneously for input from keyboard and messages from server */ if (/* FILL HERE: message from server? */) { Packet *pkt; pkt = recvpkt(sock); if (!pkt) { /* server killed, exit */ fprintf(stderr, "error: server died\n"); exit(1); } /* display the text */ if (pkt->type != USER_TEXT) { fprintf(stderr, "error: unexpected reply from server\n"); exit(1); } printf("%s: %s", pkt->text, pkt->text + strlen(pkt->text) + 1); freepkt(pkt); } if (/* FILL HERE: input from keyboard? */) { char bufr[MAXPKTLEN]; fgets(bufr, MAXPKTLEN, stdin); if (strncmp(bufr, QUIT_STRING, strlen(QUIT_STRING)) == 0) { /* leaving group */ sendpkt(sock, LEAVE_GROUP, 0, NULL); break; } /* send the text to the server */ sendpkt(sock, USER_TEXT, strlen(bufr)+1, bufr); } } } }