/***********************************************************************/ /* Course: Computer Science 402a */ /* Assignment: Assignment 3 */ /* Instructor: Mark Giesbrecht */ /* Submitted by: Dan Fraser */ /* Student Number: 001219229 */ /* Due Date: Wednesday, February 16 */ /***********************************************************************/ /* calendar.cc - Calendar implementation for the user client */ /***********************************************************************/ // see calendar.h for interface descriptions #include "calendar.h" #define TEMPSIZE 1024 #define TEMPINT_SIZE 50 pthread_mutex_t busy_mutex = PTHREAD_MUTEX_INITIALIZER; int my_uid = 0; int ns_port; string my_name; Busy busy; string nameserver_host; int main(int argc, char *argv[]) { pthread_t server_thread; int server_thread_id; pthread_attr_t server_attr; pthread_attr_init(&server_attr); if (argc < 3) { cout << "usage: " << argv[0] << " username nameserver" << endl; exit(1); } nameserver_host = argv[2]; my_name = argv[1]; printf("starting server thread\n"); server_thread_id = pthread_create(&server_thread, &server_attr, server, (void *)NULL); printf("starting main tread\n"); while (1) { string response; print_menu(); cin >> response; switch (atoi(response.c_str())) { case 1: request_meeting(); break; case 2: busy.print(); break; case 3: cancel_meeting(); break; case 5: unregister_me(); exit(0); break; } } } void print_menu() { cout << endl << "main menu------" << endl; cout << "1. request (group) meeting" << endl; cout << "2. print calendar" << endl; cout << "3. cancel meeting(originated by you)" << endl; cout << "4. look up a uid" << endl; cout << "5. exit" << endl; } void request_meeting() { int meeting_length; char temp[TEMPSIZE]; char *temp_str; vector times; vector times_backup; vector uids; Meeting *temp_meeting; string query; cout << endl << "enter length for the meeting (num of 15 min intervals): "; cin >> meeting_length; cout << "enter start times, separated by spaces: "; gets(temp); for (temp_str = strtok(temp," "); temp_str != NULL; temp_str = strtok(NULL," ")) { times.insert(times.end(),atoi(temp_str)); cout << "time " << temp_str << " inserted." << endl; } times_backup = times; cout << "enter uids, separated by spaces: "; gets(temp); for (temp_str = strtok(temp," "); temp_str != NULL; temp_str = strtok(NULL," ")) { uids.insert(uids.end(),atoi(temp_str)); cout << "uid " << temp_str << " inserted." << endl; } cout << "** adding meeting to originator's calendar" << endl; int rc = pthread_mutex_lock(&busy_mutex); if (rc) { perror("pthread_mutex lock"); pthread_exit(NULL); } temp_meeting = new Meeting(my_uid, meeting_length); for (vector::iterator p = uids.begin(); p != uids.end(); p++) { temp_meeting->addAttendee(*p); } temp_meeting->addAttendee(my_uid); temp_meeting->makeTentative(); for (vector::iterator p = times.begin(); p != times.end(); p++) { if(busy.check(*p, meeting_length)) { cout << "allocating meeting" << endl; busy.allocate(temp_meeting, *p, meeting_length); } else { cout << "erasing conflicting time" << endl; vector::iterator temp = p; times.erase(temp); } } if (times.size() <= 0) { cout << "** No meeting time possible **" << endl; busy.deallocate(temp_meeting); return; } rc = pthread_mutex_unlock(&busy_mutex); if (rc) { perror("pthread_mutex unlock"); pthread_exit(NULL); } cout << "okay, building request query" << endl; query = "meeting"; sprintf(temp, " %d %d", my_uid, meeting_length); query += temp; for (vector::const_iterator i = times.begin(); i != times.end(); i++) { sprintf(temp," %d",*i); query += temp; } cout << query << endl; for (vector::const_iterator i = uids.begin(); i != uids.end(); i++) { vector available_times; available_times = check_times(query, *i); cout << "checking availability" << endl; vector::iterator j = times.begin(); while ((j != times.end()) && (times.size() > 0)) { cout << "checking time " << *j << endl; if (find(available_times.begin(), available_times.end(), *j) == available_times.end()) { vector::iterator temp; temp = j; cout << "erasing conflicted time: " << *temp << endl; times.erase(temp); } j++; } if (times.size() == 0) { cout << "**** NO COMMON MEETING TIME POSSIBLE ****" << endl; // cancel meetings here cout << "okay, cancel request query" << endl; query = "cancel_temp"; for (vector::const_iterator i = times_backup.begin(); i != times_backup.end(); i++) { sprintf(temp," %d",*i); query += temp; } cout << "cancelling with query: "<::const_iterator i = uids.begin(); i != uids.end(); i++) { send_request(query,*i); } break; } } if (times.size() > 0) { // confirm meeting with myself cout << "* confirming local meeting" << endl; rc = pthread_mutex_lock(&busy_mutex); if (rc) { perror("pthread_mutex lock"); pthread_exit(NULL); } temp_meeting = busy.getMeeting(*times.begin()); if (!busy.deallocate(temp_meeting)) { perror("unable to deallocate local temp meeting"); return; } else { temp_meeting->makeConfirmed(); temp_meeting->setStart() = *times.begin(); busy.allocate(temp_meeting,*times.begin(), temp_meeting->getLength()); } rc = pthread_mutex_unlock(&busy_mutex); if (rc) { perror("pthread_mutex unlock"); pthread_exit(NULL); } // confirm meeting with all uid's char temp_int[TEMPINT_SIZE]; string query = "confirm "; sprintf(temp_int,"%d",*(times.begin())); query += temp_int; cout << "confirming with query: "<::const_iterator i = uids.begin(); i != uids.end(); i++) { send_request(query,*i); } } } void cancel_meeting() { char temp_int[TEMPINT_SIZE]; string cancel_message; int meeting_time; Meeting *del_meeting; vector *attendees; cout << "enter a time during the meeting to be deleted: "; cin >> meeting_time; del_meeting = busy.getMeeting(meeting_time); if (del_meeting == NULL) { cout << "there is no meeting at that time." << endl; return; } attendees = del_meeting->getAttendees(); if (find(attendees->begin(), attendees->end(), my_uid) == attendees->end()) { cout << "only the originator of a meeting can cancel it." << endl; return; } cancel_message = "cancel "; sprintf(temp_int, "%d", meeting_time); cancel_message += temp_int; for (vector::iterator p = attendees->begin(); p != attendees->end(); p++ ) { cout << "sending cancel message to uid " << *p << endl; send_request(cancel_message,*p); } } bool send_request(string request, int uid) { StreamSocket user; char buffer[TEMPSIZE]; char *temp; string again = "n"; string again2 = "n"; int result = -1; HostInfo hi("","",0); do { do { hi = uid_lookup(ns_port, uid); if (hi.getRealname() == "ERROR") { cout << "user not found in nameserver, try again (y/n): "; cin >> again2; } } while ((hi.getRealname() == "ERROR") && (again2 == "y")); if (hi.getRealname() != "ERROR") { result = user.connect(hi.getHostname(), hi.getPort()); if (result < 0) { cout << "unable to contact user, try again (y/n): "; cin >> again; } } } while ((result < 0) && (again == "y")); if (result < 0) { cout << "message send failed." << endl; return 0; } else { user.send(request); user.receive(buffer,sizeof(buffer)); temp = strtok(buffer," "); if (strcmp(temp,"OK") != 0) { perror("error returned by server"); return 0; } else { return 1; } } } vector check_times(string request, int uid) { StreamSocket user; vector times; char buffer[TEMPSIZE]; char *temp; string again = "n"; string again2 = "n"; int result = -1; HostInfo hi("","",0); do { do { hi = uid_lookup(ns_port, uid); if (hi.getRealname() == "ERROR") { cout << "user not found in nameserver, try again (y/n): "; cin >> again2; } } while ((hi.getRealname() == "ERROR") && (again2 == "y")); if (hi.getRealname() != "ERROR") { result = user.connect(hi.getHostname(), hi.getPort()); if (result < 0) { cout << "unable to contact user, try again (y/n): "; cin >> again; } } } while ((result < 0) && (again == "y")); if (result < 0) { cout << "ignoring uid, continuing with meeting setup" << endl; } else { cout << "sending request" << endl; user.send(request); cout << "waiting for response" << endl; user.receive(buffer, sizeof(buffer)); cout << "got back: " << buffer << endl; temp = strtok(buffer," "); if (strcmp(temp,"OK") != 0) { perror("invalid response from server"); return times; } else { while ((temp = strtok(NULL, " ")) != NULL) { times.insert(times.begin(), atoi(temp)); cout << "inserted time: " << atoi(temp) << endl; } } } return times; } HostInfo uid_lookup(int port, int uid) { char *request = (char*) malloc(sizeof(char) * REQUEST_SIZE); cout << "looking up user with uid " << uid << endl; HostInfo hi("","",0); rpc_hostInfo *rpc_hi; CLIENT *clnt; clnt = clnt_create(nameserver_host.c_str(), NAMESERVER, DATE_VERS, "tcp"); if (clnt <= 0) { clnt_pcreateerror("connecting to other nameserver"); exit(1); } sprintf(request, "%d",uid); rpc_hi = find_1(&uid, clnt); if (strcmp(rpc_hi->name,"OK") != 0) { printf("warning, couldn't find user\n"); } hi.setHostname() = rpc_hi->host; hi.setPort() = rpc_hi->port; hi.setRealname() = rpc_hi->name; cout << "returning from name lookup" << endl; clnt_destroy(clnt); return hi; } void unregister_me() { // char request[REQUEST_SIZE]; int *result; rpc_hostInfo hi; CLIENT *clnt; clnt = clnt_create(nameserver_host.c_str(), NAMESERVER, DATE_VERS, "tcp"); if (clnt <= 0) { perror("clnt_create"); exit(1); } printf("unregistering from nameserver\n"); hi.uid = my_uid; hi.gossip = 0; result = unregister_1(&hi, clnt); printf("back from request with: %d\n", *result); if (*result < 0) { perror("unable to unregister from nameserver"); exit(1); } clnt_destroy(clnt); }