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