/*********************************************************** * Network messages dispatcher * ************************************************************ * Description: * * * * Created by: avrami tzur * * At: Tue Aug 11 10:24:53 1992 * ***********************************************************/ /* INCLUDES */ #include #include # include "network.h" extern errno; /* Agent to dispatcher association. */ typedef struct { char agent_name[AGENT_NAME_SIZE]; char local; Sockaddr address; } agent_location; /* Agent location for each user. */ typedef struct { char user_name[USER_NAME_SIZE]; agent_location **table; int table_size; int max_entry_num; } user_agent_list; static struct { user_agent_list **table; int table_size; int max_entry_num; } users; # define USER_TABLE_INCREMENTS 5 # define AGENT_TABLE_INCREMENTS 5 /* DECLARATIONS */ void main(); static void ErrSys(char *msg); static void dispatcherInit(); static char *getOfficialName(char *name); static Sockaddr *resolveHost(register char *name); static void addUser(char *user_name, char *agent_name, Sockaddr *address, int *user_p, int *agent_p); static void locateUserAgent(char *user_name, char *agent_name, int *user_p, int *agent_p); static void dispatcherRecievPacket(); static void dispatureSendMessage(netMsgHeader *header,Sockaddr *to_address, char *data, int data_length); static void processNetMsg(char *buffer, Sockaddr *sender_address ); static void unregisterAgent(netMsgHeader *header); static void registerAgent(netMsgHeader *header); static void searchForAgent(netMsgHeader *header, Sockaddr *agent_address); static void sendToAgent(netMsgHeader *header, char *data); static void printAgents(); static void displayMessage(netMsgHeader *header, char *data); /* STATICS */ static char *my_machine; static Sockaddr *my_address; static int my_socket; /* ============================================================ | Main() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | |==========================================================| */ void main() { /* Every machine on the network have at most one dispatcher. * If an agent want to get messages from other agetns (on the * same machine or different machine) it must register itself * with the dispature. In order to find the location of a user * agent, the dispature multicust a PACKET_TYPE_SEARCH message * to all the other dispatures asking for the specific agent. * If one of the dispatcher have the agent it responds to the * message by sending its own address. The asking disputer can * cache the address for futer use. When a dispatcher recieve a * message to an agent it checks if the agent is register and * if it is it passes it the message, else it send the message * back to the sender with PACKET_TYPE_UNKNOWN_AGENT.*/ /* Initilize. */ dispatcherInit(); /* Waiting for messages */ printf("Waiting for messages\n"); while(1) dispatcherRecievPacket(); } /* ============================================================ | ErrSys() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | |==========================================================| */ static void ErrSys(char *msg) { printf("\n\nError: %s\n\n", msg); exit(1); } /* ============================================================ | dispatcherInit() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | |==========================================================| */ static void dispatcherInit() { u_short port; Sockaddr *nullAddr; Sockaddr *thisHost; char buf[128]; if(gethostname(buf, sizeof(buf)) != 0) ErrSys("Unable to get host name!"); /* Store the machine name. */ my_machine = getOfficialName(buf); /* Find the machine address. */ if ((my_address = resolveHost(buf)) == (Sockaddr *) NULL) ErrSys("Unable to resolve host address"); /* Create a socket. */ my_socket = socket(AF_INET, SOCK_DGRAM, 0); if (my_socket < 0) ErrSys("can't get socket"); /* Bind the socket. */ nullAddr = my_address; bzero((char *)&(nullAddr->sin_addr), sizeof(nullAddr->sin_addr)); nullAddr->sin_port = htons(DISPATCHER_PORT); if (bind(my_socket, nullAddr, sizeof(Sockaddr)) < 0){ if (errno != EADDRINUSE) ErrSys("netInit binding"); else ErrSys("Dispatcher port is already bound"); } my_address->sin_port = nullAddr->sin_port; /* Initilize the user table. */ users.table = (user_agent_list **)malloc(0); users.table_size = 0; users.max_entry_num = 0; } /* ============================================================ | getOfficialName() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | |==========================================================| */ static char *getOfficialName(char *name) { struct hostent *fhost; char *ret; if ((fhost = gethostbyname(name)) != NULL){ ret = (char *)malloc(strlen(fhost->h_name )+1); strcpy(ret, fhost->h_name); } else { ret = (char *)malloc(strlen(name)+1); strcpy(ret, name); } return(ret); } /* ============================================================ | resolveHost() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : Resolve the specified host name into an internet| | address. The "name" may be either a character | | string name, or an address in the form a.b.c.d | | where the pieces are octal, decimal, or hex | | numbers. Returns a pointer to a sockaddr_in | | struct (note this structure is statically | | allocated and must be copied), or NULL if the | | name is unknown. | | | | Returns: | |==========================================================| */ static Sockaddr *resolveHost(register char *name) { register struct hostent *fhost; struct in_addr fadd; Sockaddr *sa = (Sockaddr *)malloc(sizeof(Sockaddr)); if ((fhost = gethostbyname(name)) != NULL) { sa->sin_family = fhost->h_addrtype; sa->sin_port = 0; memcpy((void *)&(sa->sin_addr), (void *)fhost->h_addr, fhost->h_length); } else { fadd.s_addr = inet_addr(*name); if (fadd.s_addr != -1) { sa->sin_family = AF_INET; /* grot */ sa->sin_port = 0; sa->sin_addr.s_addr = fadd.s_addr; } else{ free(sa); return(NULL); } } return(sa); } /* ============================================================ | addUserAgent() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | |==========================================================| */ static void addUserAgent(char *user_name, char *agent_name, Sockaddr *address, int *user_p, int *agent_p) { int i, user_position=-1; int agent_position; user_agent_list *agent_list; void *temp; /* Find the user agent table. */ for(i = 0; i < users.max_entry_num; i++) if(strcmp(user_name, users.table[i]->user_name) == 0) { user_position = i; break; } if(user_position == -1) { /* User is not in the table. Add it. */ user_position = users.max_entry_num++; if(users.max_entry_num > users.table_size) { /* Increase the table. */ /* temp = malloc(sizeof(user_agent_list *)*(users.table_size + USER_TABLE_INCREMENTS)); memcpy(temp, (void *)(users.table), sizeof(user_agent_list *)*users.table_size); free(users.table); */ temp = realloc((void *)users.table, sizeof(user_agent_list *)* (users.table_size + USER_TABLE_INCREMENTS)); if(temp == NULL) ErrSys("Unable to increase the user table"); users.table_size += USER_TABLE_INCREMENTS; users.table = (user_agent_list **)temp; } /* Allocate new user entry. */ users.table[user_position] = (user_agent_list *)malloc(sizeof(user_agent_list)); strcpy(users.table[user_position]->user_name, user_name); users.table[user_position]->table = (agent_location **)malloc(0); users.table[user_position]->table_size = 0; users.table[user_position]->max_entry_num = 0; } /* Find the agent. */ agent_list = users.table[user_position]; agent_position = (agent_list->max_entry_num)++; if(agent_list->max_entry_num > agent_list->table_size){ /* Increase the table. */ temp = realloc((void *)(agent_list->table), sizeof(agent_location *)* (agent_list->table_size + USER_TABLE_INCREMENTS)); if(temp == NULL) ErrSys("Unable to increase the user agent table"); agent_list->table_size += USER_TABLE_INCREMENTS; agent_list->table = (agent_location **)temp; } /* Allocate new agent entry. */ agent_list->table[agent_position] = (agent_location *)malloc(sizeof(agent_location)); strcpy(agent_list->table[agent_position]->agent_name, agent_name); memcpy((void *)&(agent_list->table[agent_position]->address), (void *) address,sizeof(Sockaddr)); /*printf("Add %s on port %d\n", agent_name, ntohs(address->sin_port));*/ *user_p = user_position; *agent_p = agent_position; } /* ============================================================ | locateUser() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | |==========================================================| */ static void locateUser(char *user_name, char *agent_name, int *user_p, int *agent_p) { int i=0; int user_position=-1, agent_position=-1; user_agent_list *agent_list; for(i=0;iuser_name) == 0){ user_position = i; break; } } if(user_position != -1){ agent_list = users.table[user_position]; for(i=0;imax_entry_num; i++){ if(strcmp(agent_name, agent_list->table[i]->agent_name) == 0){ agent_position = i; break; } } } *user_p = user_position; *agent_p = agent_position; } /* ============================================================ | dispatcherRecievPacket() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | |==========================================================| */ static void dispatcherRecievPacket() { int addr_length = sizeof(Sockaddr); int cc; char buffer[PACKET_MAX_SIZE]; Sockaddr sender_address; cc = recvfrom(my_socket, buffer, PACKET_MAX_SIZE, 0, &sender_address, &addr_length); if (cc <= 0) { if (cc < 0 && errno != EINTR) ErrSys("event recvfrom"); } else{ if (addr_length != sizeof(struct sockaddr_in)) ErrSys("Wrong address structure!"); processNetMsg(buffer, &sender_address); } } /* ============================================================ | processNetMsg() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | |==========================================================| */ static void processNetMsg(char *buffer, Sockaddr *sender_address) { netMsgHeader *header = (netMsgHeader *)buffer; char *data = (char *)(buffer + sizeof(netMsgHeader)); netMsg *msg; header->data_length = ntohl(header->data_length); header->msg_type = ntohl(header->msg_type); printf("\tMessage length %d\n", header->data_length ); switch(header->msg_type) { case PACKET_TYPE_REGISTER:{ printf("registering user: %s agent: %s\n", header->from_user, header->from_agent); registerAgent(header); break; } case PACKET_TYPE_SEARCH_AGENT: { searchForAgent(header, sender_address); break; } case PACKET_TYPE_MESSAGE: { sendToAgent(header, data); break; } case PACKET_TYPE_UNREGISTER: { unregisterAgent(header); break; } case PACKET_TYPE_UNKNOWN_AGENT:{ printf("Unknown agent!\n"); break; } case DEBUG_PRINT_AGENTS:{ printAgents(); break; } default:{ ErrSys("Unknown message type"); } } } /* ============================================================ | printAgents() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | |==========================================================| */ static void printAgents() { int i,j; user_agent_list *agent_list; for(i=0; iuser_name); agent_list = users.table[i]; for(j=0; jmax_entry_num; j++) printf("Agent - %s port %d\n", agent_list->table[j]->agent_name, ntohs(agent_list->table[j]->address.sin_port)); } } /* ============================================================ | sendToAgent() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | |==========================================================| */ static void sendToAgent(netMsgHeader *header, char *data) { int user_p=-1, agent_p=-1; Sockaddr *dispature_address; /* Should be an agent at the current machine. */ /* Look for the destination agent address */ displayMessage(header, data); locateUser(header->to_user, header->to_agent, &user_p, &agent_p); if(agent_p != -1){ /* Forward the message to the agent */ dispatureSendMessage(header, &(users.table[user_p]->table[agent_p]->address), data, header->data_length); } else printf("Agent not found user: %s agent: %s\n",header->to_user,header->to_agent); } /* ============================================================ | registerAgent() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | |==========================================================| */ static void registerAgent(netMsgHeader *header) { int user_p=-1, agent_p=-1; /* Check if the agent is not register yet. */ locateUser(header->from_user, header->from_agent, &user_p, &agent_p); if(agent_p == -1){ /* Add the agent. */ addUserAgent(header->from_user, header->from_agent, &(header->agent_addr), &user_p, &agent_p); } } /* ============================================================ | unregisterAgent() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | |==========================================================| */ static void unregisterAgent(netMsgHeader *header) { int user_p=-1, agent_p=-1; int i; user_agent_list *agent_list; /* Check if the agent register. */ locateUser(header->from_user, header->from_agent, &user_p, &agent_p); if(agent_p != -1){ /* Delete the agent. */ agent_list = users.table[user_p]; free(agent_list->table[agent_p]); for(i=agent_p; imax_entry_num - 1; i++) agent_list->table[i] = agent_list->table[i+1]; agent_list->max_entry_num -= 1; } } /* ============================================================ | searchForAgent() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | |==========================================================| */ static void searchForAgent(netMsgHeader *header, Sockaddr *agent_address) { int user_p=-1, agent_p=-1; /* Search localy. */ locateUser(header->to_user, header->to_agent, &user_p, &agent_p); if(agent_p != -1){ /* I know this agent. */ /* Need to reply with agent address */ header->msg_type = PACKET_TYPE_AGENT_INFO; dispatureSendMessage(header, agent_address, (char *)&(users.table[user_p]->table[agent_p]->address), sizeof(Sockaddr)); } else { char *tmp = "I can not found the agent"; header->msg_type = PACKET_TYPE_UNKNOWN_AGENT ; dispatureSendMessage(header, agent_address, tmp, strlen(tmp)+1); printf("I do not have agent %s:%s\n", header->to_user, header->to_agent); } } /* ============================================================ | dispatureSendMessage() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | |==========================================================| */ static void dispatureSendMessage(netMsgHeader *header,Sockaddr *to_address, char *data, int data_length) { char buffer[PACKET_MAX_SIZE]; int cc; header->data_length = htonl(data_length); header->msg_type = htonl(header->msg_type); memcpy((void *)&(header->agent_addr), (void *)my_address, sizeof(Sockaddr)); memcpy((void *)buffer, (void *)header,sizeof(netMsgHeader)); memcpy((void *)(buffer+sizeof(netMsgHeader)), (void *)data ,data_length); cc = sendto(my_socket, buffer,PACKET_MAX_SIZE , 0,to_address, sizeof(Sockaddr)); if(cc < 0) ErrSys("Error in sanding message"); } /* ============================================================ | print_add() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: Not in use. Debuging only. | |==========================================================| */ static void print_add(struct hostent *fhost) { char *ptr; printf("Official host name: %s\n", fhost->h_name); /* Go through the list of aliases */ while((ptr = *(fhost->h_aliases)) != NULL) { printf("\t alias: %s\n", ptr); fhost->h_aliases++; } printf("\t addr_type = %d, addr_length = %d\n", fhost->h_addrtype, fhost->h_length); switch(fhost->h_addrtype) { case AF_INET: { char **listptr = fhost->h_addr_list; struct in_addr *tmp; printf("Doing it \n"); tmp = (struct in_addr *) *listptr; if(tmp == NULL) printf("NULL\n"); else printf("Not NULL\n"); printf("s_addr: %d\n", tmp->s_addr); inet_ntoa(*tmp); printf("Continue\n"); printf("\t Internet address: %s\n", inet_ntoa(*tmp)); while((tmp = (struct in_addr *) *listptr++) != NULL) printf("\t Internet address: %s\n", inet_ntoa(*tmp)); break; } default: { ErrSys("Unknown address type"); } } } /* ============================================================ | dispalyPacket() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | |==========================================================| */ static void displayMessage(netMsgHeader *header, char *data) { char *msg_type; int i; switch(header->msg_type) { case PACKET_TYPE_REGISTER: { msg_type = "PACKET_TYPE_REGISTER"; break; } case PACKET_TYPE_SEARCH_AGENT : { msg_type = "PACKET_TYPE_SEARCH"; break; } case PACKET_TYPE_MESSAGE: { msg_type = "PACKET_TYPE_MESSAGE"; break; } case PACKET_TYPE_UNREGISTER: { msg_type = "PACKET_TYPE_UNREGISTER"; break; } case PACKET_TYPE_UNKNOWN_AGENT: { msg_type = "PACKET_TYPE_UNKNOWN_AGENT"; break; } case PACKET_TYPE_AGENT_INFO: { msg_type = "PACKET_TYPE_AGENT_INFO"; break; } default: msg_type = "Unknown type"; break; } printf("\n\n\tPacket Information:\n"); printf("Type\t: %s\n", msg_type); printf("From\t: %s %s %s\n", header->from_machine,header->from_user, header->from_agent); printf("To\t: %s %s %s\n", header->to_machine,header->to_user, header->to_agent); printf("Data length: %d\n", header->data_length); printf("Data\t: "); for(i=0;idata_length;i++) printf("%c", data[i]); printf("\n\n"); }