1*16363Skarels #ifndef lint 2*16363Skarels static char sccsid[] = "@(#)invite.c 1.2 (Berkeley) 04/11/84"; 3*16363Skarels #endif 416350Skarels 516350Skarels #include "talk_ctl.h" 616350Skarels #include <sys/time.h> 716350Skarels #include <signal.h> 816350Skarels #include <setjmp.h> 916350Skarels 10*16363Skarels /* 11*16363Skarels * There wasn't an invitation waiting, so send a request containing 12*16363Skarels * our sockt address to the remote talk daemon so it can invite 13*16363Skarels * him 14*16363Skarels */ 1516350Skarels 16*16363Skarels /* 17*16363Skarels * The msg.id's for the invitations 18*16363Skarels * on the local and remote machines. 19*16363Skarels * These are used to delete the 20*16363Skarels * invitations. 21*16363Skarels */ 22*16363Skarels int local_id, remote_id; 23*16363Skarels void re_invite(); 24*16363Skarels jmp_buf invitebuf; 25*16363Skarels 2616350Skarels invite_remote() 2716350Skarels { 28*16363Skarels int nfd, read_mask, template, new_sockt; 29*16363Skarels struct itimerval itimer; 30*16363Skarels CTL_RESPONSE response; 3116350Skarels 32*16363Skarels itimer.it_value.tv_sec = RING_WAIT; 33*16363Skarels itimer.it_value.tv_usec = 0; 34*16363Skarels itimer.it_interval = itimer.it_value; 35*16363Skarels if (listen(sockt, 5) != 0) 36*16363Skarels p_error("Error on attempt to listen for caller"); 37*16363Skarels msg.addr = my_addr; 38*16363Skarels msg.id_num = -1; /* an impossible id_num */ 39*16363Skarels invitation_waiting = 1; 40*16363Skarels announce_invite(); 4116350Skarels /* 42*16363Skarels * Shut off the automatic messages for a while, 4316350Skarels * so we can use the interupt timer to resend the invitation 4416350Skarels */ 45*16363Skarels end_msgs(); 46*16363Skarels setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0); 47*16363Skarels message("Waiting for your party to respond"); 48*16363Skarels signal(SIGALRM, re_invite); 49*16363Skarels (void) setjmp(invitebuf); 50*16363Skarels while ((new_sockt = accept(sockt, 0, 0)) < 0) { 51*16363Skarels if (errno == EINTR) 52*16363Skarels continue; 53*16363Skarels p_error("Unable to connect with your party"); 5416350Skarels } 55*16363Skarels close(sockt); 56*16363Skarels sockt = new_sockt; 5716350Skarels 58*16363Skarels /* 59*16363Skarels * Have the daemons delete the invitations now that we 60*16363Skarels * have connected. 6116350Skarels */ 62*16363Skarels current_state = "Waiting for your party to respond"; 63*16363Skarels start_msgs(); 6416350Skarels 65*16363Skarels msg.id_num = local_id; 66*16363Skarels ctl_transact(my_machine_addr, msg, DELETE, &response); 67*16363Skarels msg.id_num = remote_id; 68*16363Skarels ctl_transact(his_machine_addr, msg, DELETE, &response); 69*16363Skarels invitation_waiting = 0; 7016350Skarels } 7116350Skarels 72*16363Skarels /* 73*16363Skarels * Routine called on interupt to re-invite the callee 74*16363Skarels */ 75*16363Skarels void 76*16363Skarels re_invite() 77*16363Skarels { 7816350Skarels 79*16363Skarels message("Ringing your party again"); 80*16363Skarels current_line++; 8116350Skarels /* force a re-announce */ 82*16363Skarels msg.id_num = remote_id + 1; 83*16363Skarels announce_invite(); 84*16363Skarels longjmp(invitebuf, 1); 8516350Skarels } 8616350Skarels 87*16363Skarels /* 88*16363Skarels * Transmit the invitation and process the response 89*16363Skarels */ 9016350Skarels announce_invite() 9116350Skarels { 92*16363Skarels CTL_RESPONSE response; 9316350Skarels 94*16363Skarels current_state = "Trying to connect to your party's talk daemon"; 95*16363Skarels ctl_transact(his_machine_addr, msg, ANNOUNCE, &response); 96*16363Skarels remote_id = response.id_num; 97*16363Skarels if (response.answer != SUCCESS) { 98*16363Skarels switch (response.answer) { 99*16363Skarels 100*16363Skarels case NOT_HERE : 101*16363Skarels message("Your party is not logged on"); 102*16363Skarels break; 10316350Skarels 104*16363Skarels case MACHINE_UNKNOWN : 105*16363Skarels message("Target machine does not recognize us"); 106*16363Skarels break; 10716350Skarels 108*16363Skarels case UNKNOWN_REQUEST : 109*16363Skarels message("Target machine can not handle remote talk"); 110*16363Skarels break; 11116350Skarels 112*16363Skarels case FAILED : 113*16363Skarels message("Target machine is too confused to talk to us"); 114*16363Skarels break; 11516350Skarels 116*16363Skarels case PERMISSION_DENIED : 117*16363Skarels message("Your party is refusing messages"); 118*16363Skarels break; 119*16363Skarels } 120*16363Skarels quit(); 12116350Skarels } 12216350Skarels /* leave the actual invitation on my talk daemon */ 123*16363Skarels ctl_transact(my_machine_addr, msg, LEAVE_INVITE, &response); 124*16363Skarels local_id = response.id_num; 12516350Skarels } 126*16363Skarels 127*16363Skarels /* 128*16363Skarels * Tell the daemon to remove your invitation 129*16363Skarels */ 13016350Skarels send_delete() 13116350Skarels { 13216350Skarels 133*16363Skarels msg.type = DELETE; 134*16363Skarels /* 135*16363Skarels * This is just a extra clean up, so just send it 136*16363Skarels * and don't wait for an answer 137*16363Skarels */ 138*16363Skarels msg.id_num = remote_id; 139*16363Skarels daemon_addr.sin_addr = his_machine_addr; 140*16363Skarels if (sendto(ctl_sockt, &msg, sizeof(CTL_MSG), 0, &daemon_addr, 141*16363Skarels sizeof(daemon_addr)) != sizeof(CTL_MSG)) 142*16363Skarels perror("send_delete remote"); 143*16363Skarels msg.id_num = local_id; 144*16363Skarels daemon_addr.sin_addr = my_machine_addr; 145*16363Skarels if (sendto(ctl_sockt, &msg, sizeof(CTL_MSG), 0, &daemon_addr, 146*16363Skarels sizeof(daemon_addr)) != sizeof(CTL_MSG)) 147*16363Skarels perror("send_delete local"); 14816350Skarels } 149