#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)invite.c 8.1 (Berkeley) 6/6/93";
#endif
__RCSID("$NetBSD: invite.c,v 1.10 2012/12/29 23:44:23 christos Exp $");
#endif
#include "talk.h"
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <setjmp.h>
#include <unistd.h>
#include <err.h>
#include "talk_ctl.h"
static int local_id, remote_id;
static jmp_buf invitebuf;
void
invite_remote(void)
{
int new_sockt;
struct itimerval itimer;
CTL_RESPONSE response;
itimer.it_value.tv_sec = RING_WAIT;
itimer.it_value.tv_usec = 0;
itimer.it_interval = itimer.it_value;
if (listen(sockt, 5) != 0)
p_error("Error on attempt to listen for caller");
#ifdef MSG_EOR
msg.addr = *(struct talkd_sockaddr *)(void *)&my_addr;
msg.addr.sa_family = htons(my_addr.sin_family);
#else
msg.addr = *(struct sockaddr *)&my_addr;
#endif
msg.id_num = htonl(-1);
invitation_waiting = 1;
announce_invite();
end_msgs();
setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
message("Waiting for your party to respond");
signal(SIGALRM, re_invite);
(void) setjmp(invitebuf);
while ((new_sockt = accept(sockt, 0, 0)) < 0) {
if (errno == EINTR)
continue;
p_error("Unable to connect with your party");
}
close(sockt);
sockt = new_sockt;
current_state = "Waiting for your party to respond";
start_msgs();
msg.id_num = htonl(local_id);
ctl_transact(my_machine_addr, msg, DELETE, &response);
msg.id_num = htonl(remote_id);
ctl_transact(his_machine_addr, msg, DELETE, &response);
invitation_waiting = 0;
}
void
re_invite(int dummy)
{
message("Ringing your party again");
current_line++;
msg.id_num = htonl(remote_id + 1);
announce_invite();
longjmp(invitebuf, 1);
}
static const char *answers[] = {
"answer #0",
"Your party is not logged on",
"Target machine is too confused to talk to us",
"Target machine does not recognize us",
"Your party is refusing messages",
"Target machine can not handle remote talk",
"Target machine indicates protocol mismatch",
"Target machine indicates protocol botch (addr)",
"Target machine indicates protocol botch (ctl_addr)",
};
#define NANSWERS (sizeof (answers) / sizeof (answers[0]))
void
announce_invite(void)
{
CTL_RESPONSE response;
current_state = "Trying to connect to your party's talk daemon";
ctl_transact(his_machine_addr, msg, ANNOUNCE, &response);
remote_id = response.id_num;
if (response.answer != SUCCESS) {
if (response.answer < NANSWERS)
message(answers[response.answer]);
quit();
}
ctl_transact(my_machine_addr, msg, LEAVE_INVITE, &response);
local_id = response.id_num;
}
void
send_delete(void)
{
msg.type = DELETE;
msg.id_num = htonl(remote_id);
daemon_addr.sin_addr = his_machine_addr;
if (sendto(ctl_sockt, &msg, sizeof (msg), 0,
(struct sockaddr *)&daemon_addr,
sizeof (daemon_addr)) != sizeof(msg))
warn("send_delete (remote)");
msg.id_num = htonl(local_id);
daemon_addr.sin_addr = my_machine_addr;
if (sendto(ctl_sockt, &msg, sizeof (msg), 0,
(struct sockaddr *)&daemon_addr,
sizeof (daemon_addr)) != sizeof (msg))
warn("send_delete (local)");
}