11590Srgrimes/*
21590Srgrimes * Copyright (c) 1983, 1993
31590Srgrimes *	The Regents of the University of California.  All rights reserved.
41590Srgrimes *
51590Srgrimes * Redistribution and use in source and binary forms, with or without
61590Srgrimes * modification, are permitted provided that the following conditions
71590Srgrimes * are met:
81590Srgrimes * 1. Redistributions of source code must retain the above copyright
91590Srgrimes *    notice, this list of conditions and the following disclaimer.
101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111590Srgrimes *    notice, this list of conditions and the following disclaimer in the
121590Srgrimes *    documentation and/or other materials provided with the distribution.
131590Srgrimes * 4. Neither the name of the University nor the names of its contributors
141590Srgrimes *    may be used to endorse or promote products derived from this software
151590Srgrimes *    without specific prior written permission.
161590Srgrimes *
171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271590Srgrimes * SUCH DAMAGE.
281590Srgrimes */
291590Srgrimes
3087710Smarkm#include <sys/cdefs.h>
3187710Smarkm
3287710Smarkm__FBSDID("$FreeBSD$");
3387710Smarkm
341590Srgrimes#ifndef lint
3587710Smarkmstatic const char sccsid[] = "@(#)invite.c	8.1 (Berkeley) 6/6/93";
3632503Scharnier#endif
371590Srgrimes
3887710Smarkm#include <sys/types.h>
3987710Smarkm#include <sys/socket.h>
4087710Smarkm#include <protocols/talkd.h>
4187710Smarkm
4232503Scharnier#include <err.h>
4332503Scharnier#include <errno.h>
4432503Scharnier#include <setjmp.h>
4532503Scharnier#include <signal.h>
46200418Sdelphij#include <unistd.h>
4787710Smarkm
481590Srgrimes#include "talk_ctl.h"
491590Srgrimes#include "talk.h"
501590Srgrimes
511590Srgrimes/*
521590Srgrimes * There wasn't an invitation waiting, so send a request containing
531590Srgrimes * our sockt address to the remote talk daemon so it can invite
548874Srgrimes * him
551590Srgrimes */
561590Srgrimes
571590Srgrimes/*
581590Srgrimes * The msg.id's for the invitations
591590Srgrimes * on the local and remote machines.
608874Srgrimes * These are used to delete the
611590Srgrimes * invitations.
621590Srgrimes */
63227185Sedstatic int	local_id, remote_id;
64227185Sedstatic jmp_buf invitebuf;
651590Srgrimes
6614443Sjoergvoid
67178642Sdelphijinvite_remote(void)
681590Srgrimes{
6987710Smarkm	int new_sockt;
701590Srgrimes	struct itimerval itimer;
711590Srgrimes	CTL_RESPONSE response;
721590Srgrimes
731590Srgrimes	itimer.it_value.tv_sec = RING_WAIT;
741590Srgrimes	itimer.it_value.tv_usec = 0;
751590Srgrimes	itimer.it_interval = itimer.it_value;
761590Srgrimes	if (listen(sockt, 5) != 0)
771590Srgrimes		p_error("Error on attempt to listen for caller");
781590Srgrimes#ifdef MSG_EOR
791590Srgrimes	/* copy new style sockaddr to old, swap family (short in old) */
801590Srgrimes	msg.addr = *(struct osockaddr *)&my_addr;  /* XXX new to old  style*/
811590Srgrimes	msg.addr.sa_family = htons(my_addr.sin_family);
821590Srgrimes#else
831590Srgrimes	msg.addr = *(struct sockaddr *)&my_addr;
841590Srgrimes#endif
851590Srgrimes	msg.id_num = htonl(-1);		/* an impossible id_num */
861590Srgrimes	invitation_waiting = 1;
871590Srgrimes	announce_invite();
881590Srgrimes	/*
891590Srgrimes	 * Shut off the automatic messages for a while,
90228992Suqs	 * so we can use the interrupt timer to resend the invitation
911590Srgrimes	 */
921590Srgrimes	end_msgs();
931590Srgrimes	setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
941590Srgrimes	message("Waiting for your party to respond");
951590Srgrimes	signal(SIGALRM, re_invite);
961590Srgrimes	(void) setjmp(invitebuf);
971590Srgrimes	while ((new_sockt = accept(sockt, 0, 0)) < 0) {
981590Srgrimes		if (errno == EINTR)
991590Srgrimes			continue;
1001590Srgrimes		p_error("Unable to connect with your party");
1011590Srgrimes	}
1021590Srgrimes	close(sockt);
1031590Srgrimes	sockt = new_sockt;
1041590Srgrimes
1051590Srgrimes	/*
1061590Srgrimes	 * Have the daemons delete the invitations now that we
1071590Srgrimes	 * have connected.
1081590Srgrimes	 */
1091590Srgrimes	current_state = "Waiting for your party to respond";
1101590Srgrimes	start_msgs();
1111590Srgrimes
1121590Srgrimes	msg.id_num = htonl(local_id);
1131590Srgrimes	ctl_transact(my_machine_addr, msg, DELETE, &response);
1141590Srgrimes	msg.id_num = htonl(remote_id);
1151590Srgrimes	ctl_transact(his_machine_addr, msg, DELETE, &response);
1161590Srgrimes	invitation_waiting = 0;
1171590Srgrimes}
1181590Srgrimes
1191590Srgrimes/*
120228992Suqs * Routine called on interrupt to re-invite the callee
1211590Srgrimes */
12214443Sjoerg/* ARGSUSED */
1231590Srgrimesvoid
124178642Sdelphijre_invite(int signo __unused)
1251590Srgrimes{
1261590Srgrimes
1271590Srgrimes	message("Ringing your party again");
1287451Sache	waddch(my_win.x_win, '\n');
1297451Sache	if (current_line < my_win.x_nlines - 1)
1307451Sache		current_line++;
1311590Srgrimes	/* force a re-announce */
1321590Srgrimes	msg.id_num = htonl(remote_id + 1);
1331590Srgrimes	announce_invite();
1341590Srgrimes	longjmp(invitebuf, 1);
1351590Srgrimes}
1361590Srgrimes
13787710Smarkmstatic	const char *answers[] = {
1381590Srgrimes	"answer #0",					/* SUCCESS */
1391590Srgrimes	"Your party is not logged on",			/* NOT_HERE */
1401590Srgrimes	"Target machine is too confused to talk to us",	/* FAILED */
1411590Srgrimes	"Target machine does not recognize us",		/* MACHINE_UNKNOWN */
1421590Srgrimes	"Your party is refusing messages",		/* PERMISSION_REFUSED */
1431590Srgrimes	"Target machine can not handle remote talk",	/* UNKNOWN_REQUEST */
1441590Srgrimes	"Target machine indicates protocol mismatch",	/* BADVERSION */
1451590Srgrimes	"Target machine indicates protocol botch (addr)",/* BADADDR */
1461590Srgrimes	"Target machine indicates protocol botch (ctl_addr)",/* BADCTLADDR */
1471590Srgrimes};
1481590Srgrimes#define	NANSWERS	(sizeof (answers) / sizeof (answers[0]))
1491590Srgrimes
1501590Srgrimes/*
1511590Srgrimes * Transmit the invitation and process the response
1521590Srgrimes */
15314443Sjoergvoid
154178642Sdelphijannounce_invite(void)
1551590Srgrimes{
1561590Srgrimes	CTL_RESPONSE response;
1571590Srgrimes
1581590Srgrimes	current_state = "Trying to connect to your party's talk daemon";
1591590Srgrimes	ctl_transact(his_machine_addr, msg, ANNOUNCE, &response);
1601590Srgrimes	remote_id = response.id_num;
1611590Srgrimes	if (response.answer != SUCCESS) {
1621590Srgrimes		if (response.answer < NANSWERS)
1631590Srgrimes			message(answers[response.answer]);
1641590Srgrimes		quit();
1651590Srgrimes	}
1661590Srgrimes	/* leave the actual invitation on my talk daemon */
16766682Sru	current_state = "Trying to connect to local talk daemon";
1681590Srgrimes	ctl_transact(my_machine_addr, msg, LEAVE_INVITE, &response);
1691590Srgrimes	local_id = response.id_num;
1701590Srgrimes}
1711590Srgrimes
1721590Srgrimes/*
1731590Srgrimes * Tell the daemon to remove your invitation
1741590Srgrimes */
17514443Sjoergvoid
176178642Sdelphijsend_delete(void)
1771590Srgrimes{
1781590Srgrimes
1791590Srgrimes	msg.type = DELETE;
1801590Srgrimes	/*
181108533Sschweikh	 * This is just an extra clean up, so just send it
1821590Srgrimes	 * and don't wait for an answer
1831590Srgrimes	 */
1841590Srgrimes	msg.id_num = htonl(remote_id);
1851590Srgrimes	daemon_addr.sin_addr = his_machine_addr;
1861590Srgrimes	if (sendto(ctl_sockt, &msg, sizeof (msg), 0,
1871590Srgrimes	    (struct sockaddr *)&daemon_addr,
1881590Srgrimes	    sizeof (daemon_addr)) != sizeof(msg))
18932503Scharnier		warn("send_delete (remote)");
1901590Srgrimes	msg.id_num = htonl(local_id);
1911590Srgrimes	daemon_addr.sin_addr = my_machine_addr;
1921590Srgrimes	if (sendto(ctl_sockt, &msg, sizeof (msg), 0,
1931590Srgrimes	    (struct sockaddr *)&daemon_addr,
1941590Srgrimes	    sizeof (daemon_addr)) != sizeof (msg))
19532503Scharnier		warn("send_delete (local)");
1961590Srgrimes}
197