#include <sys/types.h>
#include <sys/socket.h>
#include <protocols/talkd.h>
#include <err.h>
#include <errno.h>
#include <setjmp.h>
#include <signal.h>
#include <unistd.h>
#include "talk_ctl.h"
#include "talk.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");
msg.addr = *(struct tsockaddr *)&my_addr;
msg.addr.sa_family = htons(my_addr.sin_family);
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 signo __unused)
{
message("Ringing your party again");
waddch(my_win.x_win, '\n');
if (current_line < my_win.x_nlines - 1)
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();
}
current_state = "Trying to connect to local talk daemon";
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)");
}