xref: /csrg-svn/usr.bin/talk/invite.c (revision 16363)
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