xref: /original-bsd/usr.bin/talk/invite.c (revision 6219b5e8)
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