/*This program accepts connections from clients as well as from servers.
The server will announces its availability and the services it offers
and on which IP address/port. Dispatcher stored this information in
queues (different queues according to different services). When a client
ask for a service, dispatcher will look up the according queue (in
round-robin rotaiton), and give the server's ip address and port number
back to the client.*/
#include "service.h"
char buff[150];
char reply[150];
int sockfd;
int acsd;
struct sockaddr_in my_addr;
struct sockaddr_in client_addr;
int len=sizeof(client_addr);
int yes=1;
int myport=3498; /*fix a port for dispatcher to 3498 */
s_list *sum_s=NULL;
s_list *product_s=NULL;
int main(void)
{
char func[15]; /*to contain the function client requested.*/
char addr[50]; /*to contain the server's ip address.*/
int port; /*to contain the server's port number.*/
int status=0;
s_list *tmp;
/*create a socket, bind it to myport and listen on this port.
if status is 1,then fails.*/
if(status=bind_remote(myport,&sockfd,&my_addr)==1) exit(1);
while(1)
{
/*accept incoming connections to the dispatcher.*/
if ( (acsd = accept(sockfd, (struct sockaddr *) &client_addr, &len)) < 0)
{
perror("accept()");
exit(1);
}
/*receive message from the connection.*/
if(recv(acsd,buff,100,0)<0)
{
perror("recv");
exit(1);
}
/*If it is a message from client.*/
if(strcmp(strtok(buff," "),"client")==0)
{
printf("Received info from client %s at %d.\n",
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
strcpy(buff,strtok(0," "));
/*if the function requested is sum,look up sum list.*/
if(strcmp(buff,"sum")==0)
searchlist(&sum_s);
/*if the function requested is product,look up product list.*/
else if(strcmp(buff,"product")==0)
searchlist(&product_s);
printf("Sending server info to client at %s at %d ......",
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
/*send the server's ip address and port number (stored in reply)
to client.*/
if(send(acsd, (void *) reply, strlen(reply) + 1, 0)<0)
{
perror("send");
exit(1);
}
printf("Done!\n");
}
/*If it is a message from server.*/
else
{
printf("Received info from server %s at %d.\n",
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
strcpy(func,strtok(0," ")); /*get the services provided by server.*/
strcpy(addr,strtok(0," ")); /*get the ip address of server.*/
port=atoi(strtok(0," ")); /*get the port number of server.*/
/*create a new node */
tmp=(s_list *)malloc(sizeof(s_list));
strcpy(tmp->addr,addr);
tmp->port=port;
tmp->next=NULL;
/*if the service is sum,put it in the sum list.*/
if(strcmp(func,"sum")==0)
addlist(&sum_s,tmp);
/*if the service is product,put it int he product list.*/
else if(strcmp(func,"product")==0)
addlist(&product_s,tmp);
/*if the services provided by server are both sum and product, put
it into both sum and product list.*/
else if(strcmp(func,"both")==0)
{
addlist(&sum_s,tmp);
tmp=(s_list *)malloc(sizeof(s_list));
strcpy(tmp->addr,addr);
tmp->port=port;
addlist(&product_s,tmp);
}
/*if the service warns the dispatcher it is no longer available,
delete it from the according list.*/
else if(strcmp(func,"exit")==0)
{
deletelist(&sum_s,addr,port);
deletelist(&product_s,addr,port);
}
}
close(acsd);
}
close(sockfd);
return (0);
}
/*A function implement round-robin rotation.*/
void roundrobin(s_list **list)
{
s_list *tmp,*head;
tmp=*list;
if (*list==NULL ||(*list)->next==NULL) return;
/*go through the list, until reaches the end.*/
while(tmp->next!=NULL)
{
tmp=tmp->next;
}
/*pick up the first node, put it to the end of the queue.*/
head=(*list)->next;
tmp->next=*list;
(*list)->next=NULL;
(*list)=head;
return;
}
/*A function to get the first node of the list,and round-robin the list
once so that we will choose the next node next time.*/
void searchlist(s_list ** list)
{
s_list *tmp=*list;
if(*list==NULL) strcpy(reply,"Not Available.");
else
{
sprintf(reply,"%s %d",(*list)->addr,(*list)->port);
roundrobin(list);
}
}
/*A function to add a node to the end of the list.*/
void addlist(s_list **list,s_list *elem)
{
s_list *tmp;
tmp=*list;
if(tmp==NULL)
{
*list=elem;
return;
}
/*go throught the list, until reaches the end.*/
while(tmp->next!=NULL)
{
tmp=tmp->next;
}
/*add the node to the end of the list.*/
tmp->next=elem;
return;
}
/*A fucntion to delete a node according to the ip address and port number. */
void deletelist(s_list **list,char*addr, int port)
{
s_list *cur,*pre;
cur=*list;
pre=NULL;
if(cur==NULL)
{
printf("No server is working.\n");
return;
}
while(cur!=NULL)
{
/*if we have found the node to delete.*/
if(strcmp(cur->addr,addr)==0&& (cur->port==port))
{
if(cur==*list)
*list=cur->next;
else if(cur!=NULL)
pre->next=cur->next;
printf("deleting %s\n",inet_ntoa((*(struct in_addr*)gethostbyname(cur->addr)->h_addr)));
return;
}
pre=cur;
cur=cur->next;
}
/*After going through the list,such node is not found.*/
printf("No such server at all.\n");
return;
}