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