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