/*********************************************************** * Network support rutines * ************************************************************ * Description: * * * * Created by: avrami tzur * * At: Mon Aug 10 12:46:13 1992 * ***********************************************************/ /* INCLUDES */ # include "network.h" /* DECLARATIONS */ int netInit(char *user_name); static void getOfficialName(char *name); int getSocketNum(); static Sockaddr *resolveHost(register char *name); void sendNetMessage(char msg_type, char *from_agent, char *to_machine, char *to_user, char *to_agent, char *data, int data_length); netMsg *recieveNetMessagee(); void dispalyPacket(netMsgHeader *header, char *data); extern int errno; static Sockaddr *my_address; static int my_socket = -1; static u_short my_port; static char my_machine[MACHINE_NAME_SIZE]; static char my_user_name[USER_NAME_SIZE]; static Sockaddr *my_dispature_address; /* ============================================================ | ErrSys() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | |==========================================================| */ ErrSys(char *msg) { printf("\n\nError: %s\n\n", msg); exit(1); } /* ============================================================ | netInit() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : Network initilization rutine. | | | | Returns: | |==========================================================| */ int netInit(char *user_name) { u_short port; Sockaddr nullAddr; char buf[128]; my_port = htons(AGENT_START_PORT); if(gethostname(buf, sizeof(buf)) != 0) ErrSys("Unable to get host name!"); /* Store machine name. */ getOfficialName(buf); if ((my_address = resolveHost(buf)) == (Sockaddr *) NULL) ErrSys("Unable to resolve host address"); memcpy((void *)&nullAddr, (void *)my_address, sizeof(Sockaddr)); bzero((char *)&nullAddr.sin_addr, sizeof(nullAddr.sin_addr)); /* * Figure out which port I can use. Start at preffered_port and go * up till there's a free one. We use nullAddr so that we * can receive any incoming packet, in case there's some * multi-homed nonsense. However, not binding may cause troubles * if a specified host is on a net that causes the source of the * packets to be something other than what my_address is... * There also seems to be a problem with broadcasts not being * accepted on sockets that have an address bound to them. */ my_socket = socket(AF_INET, SOCK_DGRAM, 0); if (my_socket < 0) ErrSys("can't get socket"); for (port = ntohs(my_port); ; port++) { nullAddr.sin_port = htons(port); if (bind(my_socket, &nullAddr, sizeof(nullAddr)) < 0){ if (errno != EADDRINUSE) ErrSys("netInit binding"); else continue; } else break; } my_address->sin_port = nullAddr.sin_port; my_port = my_address->sin_port; strcpy(my_user_name, user_name); /* Initilize the dispatcher address */ my_dispature_address = (Sockaddr *)malloc(sizeof(Sockaddr)); memcpy((void *)my_dispature_address, (void *)my_address,sizeof(Sockaddr)); my_dispature_address->sin_port = DISPATCHER_PORT; printf("bind to %d\n",ntohs(my_address->sin_port)); printf("\t***Sizeof Sockaddr: %d\n", sizeof(Sockaddr)); printf("\t***Sizeof netMsgheader: %d\n", sizeof(netMsgHeader)); return(my_socket); } /* ============================================================ | getOfficialName() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | |==========================================================| */ static void getOfficialName(char *name) { struct hostent *fhost; if ((fhost = gethostbyname(name)) != NULL){ strcpy(my_machine, fhost->h_name); } else { strcpy(my_machine, name); } } /* ============================================================ | getSocketNum() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | |==========================================================| */ int getSocketNum() { return(my_socket); } /* ============================================================ | 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); } /* ============================================================ | sendNetMessage() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | |==========================================================| */ void sendNetMessage(char msg_type, char *from_agent, char *to_machine, char *to_user, char *to_agent, char *data, int data_length) { char buffer[PACKET_MAX_SIZE]; netMsgHeader *header = (netMsgHeader *)buffer; Sockaddr *dispature_address; /* Create the packet. */ header->msg_type = htonl(msg_type); strcpy(header->from_machine, my_machine); strcpy(header->from_user, my_user_name); strcpy(header->from_agent, from_agent); strcpy(header->to_machine, to_machine); strcpy(header->to_user, to_user); strcpy(header->to_agent, to_agent); memcpy((void *)&(header->agent_addr), (void *)my_address, sizeof(Sockaddr)); header->data_length = htonl(data_length); printf("\tMeesage length %d\n", header->data_length); memcpy((void *)(buffer+sizeof(netMsgHeader)), (void *)data,data_length); printf("Sending to %s %s %s\n",to_machine,to_user,to_agent); dispalyPacket(header,data); /* Remember official name. */ /* Get the target machine dispatcher address. */ if((dispature_address = resolveHost(header->to_machine)) == (Sockaddr *) NULL) ErrSys("Unable to resolve host address"); dispature_address->sin_port = htons(DISPATCHER_PORT); if(sendto(my_socket, buffer,PACKET_MAX_SIZE , 0, dispature_address, sizeof(Sockaddr))<0) ErrSys("Error in sanding message"); free(dispature_address); } /* ============================================================ | recieveNetMessage() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | |==========================================================| */ netMsg *recieveNetMessage() { int addr_length = sizeof(Sockaddr); int cc; char buffer[PACKET_MAX_SIZE]; Sockaddr sender_address; netMsgHeader *header = (netMsgHeader *)buffer; netMsg *msg= NULL; cc = recvfrom(my_socket, buffer, PACKET_MAX_SIZE, 0, &sender_address, &addr_length); if (cc <= 0) { if (cc < 0 && errno != EINTR) ErrSys("event recvfrom"); } if (addr_length != sizeof(struct sockaddr_in)) ErrSys("Wrong address structure!"); /* Convert data length representation. */ header->data_length = ntohl(header->data_length); /* Convert message type represantation */ header->msg_type = ntohl(header->msg_type); /* Allocate net message. */ msg = (netMsg *)malloc(sizeof(netMsg)); /* Allocate data space. */ msg->data = (char *)malloc(header->data_length); /* Copy the header. */ memcpy((void *)msg, (void *)header, sizeof(netMsgHeader)); /* Copy the data. */ memcpy((void *)msg->data, (void *)(buffer + sizeof(netMsgHeader)),header->data_length); return(msg); } /* ============================================================ | dispalyPacket() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | |==========================================================| */ void dispalyPacket(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"); }