/***********************************************************************/ /* Course: Computer Science 402a */ /* Assignment: Assignment 3 */ /* Instructor: Mark Giesbrecht */ /* Submitted by: Dan Fraser */ /* Student Number: 001219229 */ /* Due Date: Wednesday, February 16 */ /***********************************************************************/ /* nameserver.cc -- Implementation of the nameserver. */ /***********************************************************************/ #define RETURN_SIZE 1024 #define TEMPINT_SIZE 50 #define HOST_SIZE 80 #include "nameserver.h" #include "StreamSocket.h" #include #include "HostInfo.h" #include #include #include #include vector Registry; vector Nameservers; map Names; map Names_cache; static bool first_run = 1; int register_gossip(rpc_hostInfo data); int unregister_gossip(rpc_hostInfo data); int lazy_init(); /************************************************************************ Function Name: register Input Parameters: data - input string with name, ip, port separated by spaces Output Parameters: returns result string and UID Description: registers user, adds to local database, returns a UID. ************************************************************************/ int *register_1_svc(rpc_hostInfo *data, struct svc_req *req) { static int result; string Name; lazy_init(); printf("starting registration\n"); printf("name: %s, ip: %s, port: %d\n",data->name, data->host, data->port); Name = data->name; HostInfo hostinfo(data->name, data->host, data->port); if (data->uid > 0) { printf("forcing uid as %d\n",data->uid); hostinfo.setUID() = data->uid; } if (Names_cache.find(Name) != Names_cache.end()) { if (find(Registry.begin(), Registry.end(),Names_cache[Name]) == Registry.end()) { hostinfo.setUID() = Names_cache[Name]; } else { cout << "warning: attempt to have two active users with same name" << endl; } } int UID = hostinfo.getUID(); Registry.insert(Registry.end(), hostinfo); Names[Name] = UID; Names_cache[Name] = UID; result = UID; cout << "register: "<< result << endl; if (data->gossip == 0) { data->uid = UID; if (register_gossip(*data) < 0) { result = -1; } } return &result; } /************************************************************************ Function Name: unregister Input Parameters: data - string containing uid to delete Output Parameters: result string Description: removes user from local databases ************************************************************************/ int* unregister_1_svc(rpc_hostInfo *data, struct svc_req *req) { int UID = data->uid; static int result; lazy_init(); vector::iterator p = find(Registry.begin(), Registry.end(),UID); if ( p == Registry.end() ) { cout << "can't find " << UID <<" to unregister" << endl; result = -1; return &result; } else { Names.erase(p->getRealname()); Registry.erase(p); cout << UID << " erased." << endl; result = UID; if (data->gossip == 0) { if (unregister_gossip(*data) < 0) { result = -1; } } return &result; } } /************************************************************************ Function Name: find Input Parameters: data - string with uid of user to find Output Parameters: result string with hostname and portnumber. Description: looks up user in database, returns hostname and port. ************************************************************************/ rpc_hostInfo *find_1_svc(int *data, struct svc_req *req) { static rpc_hostInfo hi; int UID = *data; lazy_init(); vector::iterator p = find(Registry.begin(), Registry.end(),UID); if ( p == Registry.end() ) { cout << "can't find " << UID << endl; hi.name = strdup("ERROR"); return &hi; } else { cout << "found user" << endl; hi.name = strdup("OK"); hi.host = strdup(p->getHostname().c_str()); hi.port = p->getPort(); return &hi; } } /************************************************************************ Function Name: findname Input Parameters: data - string containing name to find Output Parameters: result string with uid Description: returns result string with uid of found user. ************************************************************************/ int *findname_1_svc(char **data, struct svc_req *req) { static int result; lazy_init(); string Name = *data; cout << "trying to return uid for " << Name << "." << endl; int UID = Names[*data]; cout <<" got " << UID << " from map." << endl; if ( UID <= 0 ) { cout << "can't find " << UID << endl; result = -1; return &result; } else { result = UID; return &result; } } /************************************************************************ Function Name: lazy_init Input Parameters: n/a Output Parameters: n/a Description: reads nameserver configuration file, connects to other nameservers in network ************************************************************************/ int lazy_init() { FILE *fp; CLIENT *clnt; if (first_run) { first_run = 0; char hostname[HOST_SIZE]; printf("running initialization\n"); // do initialize stuff if ((fp = fopen("nameserver.dat", "r")) == NULL) { perror("data file open"); exit(1); } do { hostname[0] = 0; fgets(hostname, sizeof(hostname), fp); hostname[strlen(hostname)-1] = 0; if (strlen(hostname)) { printf("found hostname: %s\n", hostname); clnt = clnt_create(hostname, NAMESERVER, DATE_VERS, "tcp"); if (clnt <= 0) { clnt_pcreateerror("connecting to other nameserver"); exit(1); } Nameservers.push_back(clnt); } } while (!feof(fp)); return 1; } return 0; } /************************************************************************ Function Name: register_gossip Input Parameters: rpc_hostdata structure Output Parameters: n/a Description: connects to all known nameservers and sends them the information requried to register the person in question. The remote server should then complete the registration. ************************************************************************/ int register_gossip(rpc_hostInfo data) { int *result; printf("register gossip\n"); data.gossip = 1; for (vector::iterator i = Nameservers.begin(); i != Nameservers.end(); i++) { result = register_1(&data, *i); } return 0; } /************************************************************************ Function Name: unregister_gossip Input Parameters: rpc_hostdata structure Output Parameters: n/a Description: connects to all known nameservers and sends them the information requried to unregister the person in question. The remote server should then complete the unregistration. ************************************************************************/ int unregister_gossip(rpc_hostInfo data) { int *result; printf("unregsiter gossip\n"); data.gossip = 1; for (vector::iterator i = Nameservers.begin(); i != Nameservers.end(); i++) { result = unregister_1(&data, *i); } return 0; }