Exemplo n.º 1
0
int main(int argc, char *argv[]){
	init();
	_listen();
	char ticketMessage[32];
	char read_buf[MAXBUF];
	int i;
	int sfd;
	for(;;){
		refreshSelect();
		int maxfd = getMaxFD();
		bool isClient = true;
		if (select(maxfd+1,&read_fd,NULL,NULL,NULL)){
			for(i=0;i<CLI_FD;i++){
				if(FD_ISSET(g_sfd[i],&read_fd)){
					sfd = g_sfd[i];
					break;
				}
				if(FD_ISSET(service_sfd[i],&read_fd)){
					service_(service_sfd[i]);
					isClient = false;
					break;
				}
			}
		}
		if(isClient){
			clilen[i] = sizeof(clients[i]);
			int nsfd = accept(sfd,(struct sockaddr *) &clients[i], &clilen[i]);
			char *buf;
			bzero(ticketMessage, 32);
			bzero(read_buf,MAXBUF);
			//strcpy(buf,"Which mall do you want to connect to?");
			buf = "Which mall do you want to connect to?";
			int len = strlen(buf);
			send(nsfd, buf, len, 0);

			int n;
			n = recv(nsfd,read_buf,MAXBUF,0);
			printf("The client wants to connect to - %s\n",read_buf);

			int ticket = getTicket();
			sprintf(ticketMessage, "%d:%d ", PORT_C, ticket);
			send(nsfd, ticketMessage, strlen(ticketMessage), 0);
			close(nsfd);
		}	
	}
}
int server(char* port) {

	int completed=0;


	node *IP_list = NULL;
	int noOfConnections=0;
	int cmdNo;

	fd_set read_fds, write_fds,read_fds_copy,write_fds_copy;
	FD_ZERO(&read_fds);
	FD_ZERO(&write_fds);
	
	//int fdMax = STDIN_FILENO;
	int fdMax = 0; // 0 is file descriptor for standard input 
	int serverSocket, nSocket,selected;  
	struct sockaddr_in serverAddress,clientAddress;
	struct sockaddr_storage getPeerInfo;
	socklen_t clientAddrLen = sizeof(clientAddress);

	char msg[5000]; 
	int numBytes;

	serverSocket= socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);  

	printf("Server created \n");
	
	if(serverSocket == -1) {
		printf("Server: Socket creation failed\n");
	}

	fdMax = serverSocket;
	/* Beej: Allows other sockets to bind() to this port, unless there is an active listening socket bound to the port already. 
	This enables you to get around those "Address already in use" error messages when you try to restart your server after a crash. */
	int socketReuse = 1; 
	setsockopt(serverSocket,SOL_SOCKET,SO_REUSEADDR,&socketReuse,sizeof(int));


	serverAddress.sin_addr.s_addr = INADDR_ANY;
	serverAddress.sin_family = AF_INET;
	serverAddress.sin_port = htons(atoi(port)); //network Byte order

	// bind
	if(bind(serverSocket,(struct sockaddr*)&serverAddress,sizeof(serverAddress))== -1) {
		printf("Server: Binding failed\n");
		close(serverSocket); 
	}
	printf("Server has been bound to port %d \n",atoi(port));

	//printf("Server sockets is %d \n",serverSocket);

	listen(serverSocket,10);

	FD_SET(STDIN_FILENO,&read_fds);
	FD_SET(serverSocket,&read_fds);
	
	while(1) {
		// Create copies of fd_sets because select will modify them
		read_fds_copy = read_fds;
		write_fds_copy = write_fds;
		if (select(fdMax+1, &read_fds_copy,NULL, NULL, NULL) == -1) {
			perror("Server : Select error");
			continue;
		}
		for(selected = 0;selected<=fdMax;selected++) {
			if(FD_ISSET(selected,&read_fds_copy)) {
				/* Need to handle  3 scenarios
				1. Data available from Server socket (New Client arrives)
				2. Data available from Standard Input (Commands)
				3. Data available from clients (SYNC? )
				*/
				if(selected==serverSocket){ // Scenario 1
					printf("Server : A client is trying to connect.\n");
					
					memset(&clientAddress, 0, sizeof(clientAddrLen));
					if ((nSocket = accept(serverSocket,(struct sockaddr*)&clientAddress,&clientAddrLen))==-1) {
						printf("Server: Accept failed\n");
					}
					
					if (noOfConnections >= 4) {
						close(nSocket);
						printf("Server : Connection limit exceeded!\n");
						continue;
					}

					memset(msg,0,5000);
					// receive clients listening port number
					numBytes = recv(nSocket,msg,5000,0);
					printf("New connection from %s : %d \n",inet_ntoa(clientAddress.sin_addr),atoi(msg));
					printf("Client has been registered .Yay!\n");


					setsockopt(nSocket,SOL_SOCKET,SO_REUSEADDR,&socketReuse,sizeof(int));
					push(clientAddress,nSocket,atoi(msg),&IP_list);
										noOfConnections++;

					sendAll(IP_list,noOfConnections);
					FD_SET(nSocket,&read_fds);
					
					if(nSocket > fdMax) 
						fdMax = nSocket;
				} // End Scenario 1
				if(selected==0){ // Scenario 2
					memset(msg,0,sizeof(msg)); // clear msg array
					if ((numBytes = read(selected, msg, sizeof(msg))) <= 0)
						perror("Server read error");

					cmdNo=parse(msg);
					int fd;

					switch(cmdNo){
						case 0: // HELP
						help();
						break;
						case 1:
						creator(); //CREATOR
						break;
						case 2:
						display(port,1); //DISPLAY 
						break;
						case 3: //REGISTER
						printf("REGISTER command not available for server\n");
						break;
						case 4: //CONNECT 
						printf("CONNECT command not available for server\n");
						break;
						case 5: //LIST
						displayList(IP_list); 
						break;
						case 6: //TERMINATE 
						fd=terminate(&IP_list);
                            if(fd!=-1){
                                FD_CLR(fd,&read_fds);
                                FD_CLR(fd,&write_fds);

                                fdMax = getMaxFD(IP_list);
                                noOfConnections--;
                                if(noOfConnections==0){
                                    IP_list=NULL;
                                }

                            }
                            else{
                                printf("Invalid connection ID \n");

                            }
						break;
						break;
						case 7: //QUIT
						quit(&IP_list);
						return 1;
						break;
						case 8: //GET
						printf("GET command not available for server\n");
						break;
						case 9: //PUT
						printf("PUT command not available for server\n");
						break;
						case 10: //SYNC
						printf("SYNC command not available for server\n");
						break;
					}
				} // End Scenario 2

                else { // Scenario 3

					if ((numBytes = recv(selected, msg, 5000, 0)) <= 0) {
						if (numBytes == 0)
						{

							if(getpeername(selected,(struct sockaddr*)&getPeerInfo,&clientAddrLen)<0)
							{
								perror("Server : Error\n");
								return 0;
							}

							struct sockaddr_in *s = (struct sockaddr_in *)&getPeerInfo;

							char* IPAdd = (char*)malloc(sizeof(char)*INET6_ADDRSTRLEN);
							int targetPort = ntohs(ntohs(s->sin_port));
							inet_ntop(AF_INET, &(s->sin_addr), IPAdd, INET6_ADDRSTRLEN);

							printf("Server: Connection closed by IP %s\n",IPAdd);

							
							delete(IPAdd,targetPort,&IP_list);
							FD_CLR(selected,&read_fds);
							close(selected);
							noOfConnections--;

							if(noOfConnections == 0){
								printf("All connections are closed\n");
								IP_list=NULL;}
							else
							{
								// Broad cast current peer list
								fdMax = getMaxFD(IP_list);
								sendAll(IP_list,noOfConnections);
								
							}
						}
						else
						{
							//perror("Server");
						}
					}
					else// we got some data from a client
					{


						char command1[4];
						char command2[6];
                        memcpy(command1,msg,4); // Extract first 3 characters from incoming data
                        memcpy(command2,msg,6); // Extract first 3 characters from incoming data


                        if(!(strcmp(command1,"SYNC")) || (!(strcmp(command1,"sync")))) { // Check if it is GET command


                        	printf("Triggering SYNC on all connected peers!\n");


                        	node *curr=IP_list;
                        	
							syncRelay(curr);
							memset(msg,0,5000); // reset read buffer
							curr=curr->next;
							completed++;
					



                        }


                        else if(!(strcmp(command2,"E_SYNC")) || (!(strcmp(command2,"e_sync")))) { // Check if it is GET command

                        	printf("ESYNC received\n");
                        	int i;

                        	node *curr=IP_list;


                        	if(completed!=noOfConnections){
                        		for(i=0;i<completed;i++){
                        			curr=curr->next;
                        		}
                        		syncRelay(curr);
                        		completed++;
                        	}
                        	else if(completed==noOfConnections){
                        		completed=0;
                        	}


							memset(msg,0,5000); // reset read buffer



                        }

					}
                }
			}
		}
	}
}