/* slavesel.c
 * 
 * Example of slave using TCP protocol.
 * Reference: W. Richard Stevens. "UNIX Network Programming". 
 *						Prentice Hall Software Series. 1990.
 *						Chapter 6: Berkeley Sockets.
 * $Id: slave.c,v 1.3 2003/08/04 03:09:44 tmacam Exp $
 */

#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>

#include "common.h"
#include "search.h"

int process_request( slave_request *request, slave_response *response)
{
	int matches_found = 0;
	int error = 0;
	
	printf("\taprox_k=%i\n\tpattern='%s'\n\tfilename='%s'\n", request->approx_k, request->pattern, request->filename);

	matches_found = do_search_request(request, &error); 
	if (error){
		response->matches_found = 0;
		return -1;
	} else {
		response->matches_found = matches_found;
	}

	return 0;
}



/***********************************************/
/* Function: main                              */
/***********************************************/
int main(int argc, char *argv[])
{
	int sockfd, newsockfd, clilen;
	struct sockaddr_in cli_addr, serv_addr;
	slave_request request;
	slave_response response;		
	int response_len;
	unsigned long start_time;	/* Contabilidade de tempo */
		
	/* Open a TCP socket (an Internet stream socket). */		
	if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
		fprintf(stderr,"slave: can't open stream socket\n");	
	}
	
	/* Bind our local address so that the master can send to us. */		
	bzero((char *) &serv_addr, sizeof(serv_addr));
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	serv_addr.sin_port = htons(SERV_TCP_PORT);		
	if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0){
		fprintf(stderr,"slave: can't bind local address\n");
	}		
	listen(sockfd, 5);

	/* Sirva requisições até morrer :-) */
	for (;;){	
		/* Wait for a connection from the master process. */
		clilen = sizeof(cli_addr);
		printf("slave: ready to accept connection request\n");
		newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);	
		if (newsockfd < 0){
			fprintf(stderr,"slave: accept error\n");
		}
		printf("slave: ready to receive request\n");
		
		/* Receive the request from the master. */		 
		if (recv(newsockfd, (void *) &request, sizeof(request), MSG_WAITALL|MSG_NOSIGNAL) < 0){
			fprintf(stderr,"slave: can't receive request\n");		
			close(newsockfd);
			exit(1);
		}
		printf("slave: request received. Processing...\n");
		
		/* Process the request. */	
		start_time = get_long_time();
		process_request(&request,&response);
		response.process_time = get_long_time() - start_time;
		
		/* Send the response to the master. */
		response_len = sizeof(response);
		if (sendall(newsockfd, (void *) &response, &response_len) < 0){
			fprintf(stderr,"slave: can't send response\n");		
			close(newsockfd);
			exit(1);
		}
	}// for(;;)
	close(newsockfd);
	close(sockfd);
	exit(0);
}
