#include #include #include #include #include #include #include #include #include #include #include #include #include "tools.h" #define SERVERPORT 3018 // the port users will be connecting to #define PORT_MY_ID_LAST_3_DIG 294 #define PORT_PEER_UDP_BASE 5100 #define PORT_OFFSET_PER_PEER 100 #define MY_UDP_PORT(Peer_Num) (PORT_PEER_UDP_BASE+PORT_OFFSET_PER_PEER*Peer_Num+PORT_MY_ID_LAST_3_DIG) #define TEMP_BUF_SIZE 100 #define BACKLOG 2 struct SGROUP_Info{ char name[6];//the name of the peer char c_port_num[6];// port number stored in characters unsigned int i_port_num;// port number stored in integer }; typedef struct SGROUP_Info SGROUP_Info; SGROUP_Info g_info[4]; char* peerName[4] = {"peer1","peer2","peer3","peer4"}; char groupNum; char InBuf1[TEMP_BUF_SIZE]; char InBuf2[TEMP_BUF_SIZE]; char OutBuf1[TEMP_BUF_SIZE]; char OutBuf2[TEMP_BUF_SIZE]; int peerID=1; /************************************************** * void Store_Group_member(char *buf,int id) * function: store the name and TCP port number of received data. * parameter: * buf: the buffer that stored the information * id: the order of the received data ***************************************************/ void Store_Group_member(char *buf,int id) { int i,j; char tmpStr[8]; getStrSegment(buf, tmpStr,2); strcpy(g_info[id].name,tmpStr); getStrSegment(buf, tmpStr,3); strcpy(g_info[id].c_port_num,tmpStr); g_info[id].i_port_num=a5toi(g_info[id].c_port_num); } /*************************************************** * int CheckGroupsize(int pID,char* buf) * function: check the group size , the data hidden in the received data buffer. * return value: * the group size * param * buf: the pointer of the received buffer ****************************************************/ int CheckGroupsize(int pID,char* buf) { int i,j; char tmpStr[8]; getStrSegment(buf, tmpStr,2);//get group size switch(tmpStr[0]){ case '0':return 0; case '1':return 1; case '2':return 2; case '3':return 3; case '4':return 4; default: printf("get group size error\n"); return 99; break; } } /**************************************************** * void strcatName(void) * function:append the sender's name to the string *****************************************************/ void strcatName(void) { memset(OutBuf1, '\0',TEMP_BUF_SIZE); strcat(OutBuf1,peerName[peerID-1]); } /**************************************************** * void strcatGroupSize(int size) * function:append the group's size to the string * param: * size: the group size *****************************************************/ void strcatGroupSize(int size) { strcat(OutBuf1," "); memset(OutBuf2, '\0',TEMP_BUF_SIZE); itostr(OutBuf2, size) ; OutBuf2[1]='\0'; strcat(OutBuf1, OutBuf2); } /**************************************************** * void strcatGroupNumber(void) * function:append the group number to the string *****************************************************/ void strcatGroupNumber(void) { int num; num = strlen(OutBuf1); OutBuf1[num] = groupNum; OutBuf1[num+1] = '\0'; } /**************************************************** * void send_ackr(void) * function:send ack to the designated socket *****************************************************/ void send_ack(int fd) { if (send(fd, "ack", 3, 0) == -1){ perror("send"); exit(1); } } /**************************************************** * void rcv_ack(int fd) * function:wait a ack from the designated port *****************************************************/ void rcv_ack(int fd) { int numbytes; if ((numbytes=recv(fd, OutBuf1, 19, 0)) == -1) { perror("ack"); exit(1); } } /**************************************************** * void sendDataToGroupPeer(int pID,int size) * function:send the group information to peers belong to the same group * para: * pid, peer ID * size, group size *****************************************************/ void sendDataToGroupPeer(int pID,int size) { int sockfd, numbytes; int i,j; int stop = 0; struct hostent *he; int newSize = size -1; struct sockaddr_in their_addr; // connector's address information /***************************************** * Open a new TCP socket *****************************************/ if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } if ((he=gethostbyname("localhost")) == NULL) { perror("gethostbyname"); exit(1); } their_addr.sin_family = AF_INET; their_addr.sin_port = htons(g_info[0].i_port_num); their_addr.sin_addr = *((struct in_addr *)he->h_addr); memset(&(their_addr.sin_zero), '\0', 8); if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1) { perror("connect"); exit(1); } /***************************************** * send message 1 ******************************************/ strcatName(); strcatGroupSize(newSize); if (send(sockfd, OutBuf1, strlen(OutBuf1), 0) == -1) perror("send"); rcv_ack(sockfd); /***************************************** * send message 2 ******************************************/ strcatName(); strcat(OutBuf1," welcome to group"); strcatGroupNumber(); if (send(sockfd, OutBuf1, strlen(OutBuf1), 0) == -1) perror("send"); rcv_ack(sockfd); /***************************************** * send rest message ******************************************/ if(newSize>1){ for(i=0; ih_addr); // automatically fill with my IP memset(&(my_TCP_addr.sin_zero), '\0', 8); // zero the rest of the struct /*bind TCP port assigned by kernel*/ if (bind(TCP_sockfd, (struct sockaddr *)&my_TCP_addr, sizeof(struct sockaddr)) == -1) { perror("bind"); exit(1); } /*get the socket info assigned by kernel*/ if(getsockname(TCP_sockfd,(struct sockaddr *)&my_TCP_addr,&len )<0){ perror("getsockname"); exit(1); } /*open the UDP*/ if ((UDP_sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { perror("UDPsocket"); exit(1); } /*create a UDP socket and bind a dedicated port*/ my_UDP_addr.sin_family = AF_INET; // host byte order my_UDP_addr.sin_port = htons(MY_UDP_PORT(peerID-1)); // short, network byte order my_UDP_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP memset(&(my_UDP_addr.sin_zero), '\0', 8); // zero the rest of the struct if (bind(UDP_sockfd, (struct sockaddr *)&my_UDP_addr, sizeof(struct sockaddr)) == -1) { perror("bind"); exit(1); } /* Try to send the registration data*/ /*a) peer name*/ memset(OutBuf1, '\0',TEMP_BUF_SIZE); strcat(OutBuf1,peerName[peerID-1]); /*b). TCP port number*/ strcat(OutBuf1," "); memset(OutBuf2, '\0',TEMP_BUF_SIZE); itostr(OutBuf2, my_TCP_addr.sin_port) ; OutBuf2[5]='\0'; strcat(OutBuf1, OutBuf2); /*c). IP Address*/ strcat(OutBuf1," "); strcat(OutBuf1,inet_ntoa(my_TCP_addr.sin_addr)); /*d). group number*/ srand ( time(NULL)+peerID); if(rand()%2){ groupNum = '1'; }else{ groupNum = '2'; } strcat(OutBuf1," "); memset(OutBuf2, '\0',TEMP_BUF_SIZE); memcpy(OutBuf2,&groupNum,1); OutBuf2[1]='\0'; strcat(OutBuf1, OutBuf2); their_addr.sin_family = AF_INET; // host byte order their_addr.sin_port = htons(SERVERPORT); // short, network byte order their_addr.sin_addr = *((struct in_addr *)he->h_addr); memset(&(their_addr.sin_zero), '\0', 8); // zero the rest of the struct /*send the registration data to boot strap server*/ if ((numbytes = sendto(UDP_sockfd, OutBuf1, strlen(OutBuf1), 0, (struct sockaddr *)&their_addr, sizeof(struct sockaddr))) == -1) { perror("sendto"); exit(1); } close(UDP_sockfd); /*listen on the TCP port*/ if (listen(TCP_sockfd, BACKLOG) == -1) { perror("listen"); exit(1); } sin_size = sizeof(struct sockaddr_in); if ((new_fd = accept(TCP_sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) { perror("accept"); } memset(OutBuf2, '\0',TEMP_BUF_SIZE); /*received a group information*/ if ((numbytes=recv(new_fd, OutBuf2, TEMP_BUF_SIZE-1, 0)) == -1) { perror("recv"); exit(1); } OutBuf2[numbytes] = '\0'; g_size=CheckGroupsize(peerID,OutBuf2); send_ack(new_fd); //receive welcome message if ((numbytes=recv(new_fd, OutBuf2, TEMP_BUF_SIZE-1, 0)) == -1) { perror("recv"); exit(1); } OutBuf2[numbytes] = '\0'; send_ack(new_fd); if(g_size == 1){// show the message and terminate printf("Peer%d joined group %c\n",peerID,groupNum); close(TCP_sockfd); close(new_fd); exit(1); }else{// receiving the rest group data for(i = 0 ;i< g_size -1;i++){ memset(InBuf1, '\0',TEMP_BUF_SIZE); if ((numbytes=recv(new_fd, InBuf1, TEMP_BUF_SIZE-1, 0)) == -1) { perror("recv"); exit(1); } InBuf1[numbytes] = '\0'; Store_Group_member(InBuf1,i); send_ack(new_fd); } close(new_fd); // parent doesn't need this } printf("Peer%d joined group %c\n",peerID,groupNum); sendDataToGroupPeer(peerID,g_size); close(TCP_sockfd); close(new_fd); exit(1); }