1*22394Sdist /* 2*22394Sdist * Copyright (c) 1983 Regents of the University of California. 3*22394Sdist * All rights reserved. The Berkeley software License Agreement 4*22394Sdist * specifies the terms and conditions for redistribution. 5*22394Sdist */ 6*22394Sdist 716363Skarels #ifndef lint 8*22394Sdist static char sccsid[] = "@(#)invite.c 5.1 (Berkeley) 06/06/85"; 9*22394Sdist #endif not lint 1016350Skarels 1116350Skarels #include "talk_ctl.h" 1216350Skarels #include <sys/time.h> 1316350Skarels #include <signal.h> 1416350Skarels #include <setjmp.h> 1516350Skarels 1616363Skarels /* 1716363Skarels * There wasn't an invitation waiting, so send a request containing 1816363Skarels * our sockt address to the remote talk daemon so it can invite 1916363Skarels * him 2016363Skarels */ 2116350Skarels 2216363Skarels /* 2316363Skarels * The msg.id's for the invitations 2416363Skarels * on the local and remote machines. 2516363Skarels * These are used to delete the 2616363Skarels * invitations. 2716363Skarels */ 2816363Skarels int local_id, remote_id; 2916363Skarels void re_invite(); 3016363Skarels jmp_buf invitebuf; 3116363Skarels 3216350Skarels invite_remote() 3316350Skarels { 3416363Skarels int nfd, read_mask, template, new_sockt; 3516363Skarels struct itimerval itimer; 3616363Skarels CTL_RESPONSE response; 3716350Skarels 3816363Skarels itimer.it_value.tv_sec = RING_WAIT; 3916363Skarels itimer.it_value.tv_usec = 0; 4016363Skarels itimer.it_interval = itimer.it_value; 4116363Skarels if (listen(sockt, 5) != 0) 4216363Skarels p_error("Error on attempt to listen for caller"); 4316363Skarels msg.addr = my_addr; 4416363Skarels msg.id_num = -1; /* an impossible id_num */ 4516363Skarels invitation_waiting = 1; 4616363Skarels announce_invite(); 4716350Skarels /* 4816363Skarels * Shut off the automatic messages for a while, 4916350Skarels * so we can use the interupt timer to resend the invitation 5016350Skarels */ 5116363Skarels end_msgs(); 5216363Skarels setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0); 5316363Skarels message("Waiting for your party to respond"); 5416363Skarels signal(SIGALRM, re_invite); 5516363Skarels (void) setjmp(invitebuf); 5616363Skarels while ((new_sockt = accept(sockt, 0, 0)) < 0) { 5716363Skarels if (errno == EINTR) 5816363Skarels continue; 5916363Skarels p_error("Unable to connect with your party"); 6016350Skarels } 6116363Skarels close(sockt); 6216363Skarels sockt = new_sockt; 6316350Skarels 6416363Skarels /* 6516363Skarels * Have the daemons delete the invitations now that we 6616363Skarels * have connected. 6716350Skarels */ 6816363Skarels current_state = "Waiting for your party to respond"; 6916363Skarels start_msgs(); 7016350Skarels 7116363Skarels msg.id_num = local_id; 7216363Skarels ctl_transact(my_machine_addr, msg, DELETE, &response); 7316363Skarels msg.id_num = remote_id; 7416363Skarels ctl_transact(his_machine_addr, msg, DELETE, &response); 7516363Skarels invitation_waiting = 0; 7616350Skarels } 7716350Skarels 7816363Skarels /* 7916363Skarels * Routine called on interupt to re-invite the callee 8016363Skarels */ 8116363Skarels void 8216363Skarels re_invite() 8316363Skarels { 8416350Skarels 8516363Skarels message("Ringing your party again"); 8616363Skarels current_line++; 8716350Skarels /* force a re-announce */ 8816363Skarels msg.id_num = remote_id + 1; 8916363Skarels announce_invite(); 9016363Skarels longjmp(invitebuf, 1); 9116350Skarels } 9216350Skarels 9316363Skarels /* 9416363Skarels * Transmit the invitation and process the response 9516363Skarels */ 9616350Skarels announce_invite() 9716350Skarels { 9816363Skarels CTL_RESPONSE response; 9916350Skarels 10016363Skarels current_state = "Trying to connect to your party's talk daemon"; 10116363Skarels ctl_transact(his_machine_addr, msg, ANNOUNCE, &response); 10216363Skarels remote_id = response.id_num; 10316363Skarels if (response.answer != SUCCESS) { 10416363Skarels switch (response.answer) { 10516363Skarels 10616363Skarels case NOT_HERE : 10716363Skarels message("Your party is not logged on"); 10816363Skarels break; 10916350Skarels 11016363Skarels case MACHINE_UNKNOWN : 11116363Skarels message("Target machine does not recognize us"); 11216363Skarels break; 11316350Skarels 11416363Skarels case UNKNOWN_REQUEST : 11516363Skarels message("Target machine can not handle remote talk"); 11616363Skarels break; 11716350Skarels 11816363Skarels case FAILED : 11916363Skarels message("Target machine is too confused to talk to us"); 12016363Skarels break; 12116350Skarels 12216363Skarels case PERMISSION_DENIED : 12316363Skarels message("Your party is refusing messages"); 12416363Skarels break; 12516363Skarels } 12616363Skarels quit(); 12716350Skarels } 12816350Skarels /* leave the actual invitation on my talk daemon */ 12916363Skarels ctl_transact(my_machine_addr, msg, LEAVE_INVITE, &response); 13016363Skarels local_id = response.id_num; 13116350Skarels } 13216363Skarels 13316363Skarels /* 13416363Skarels * Tell the daemon to remove your invitation 13516363Skarels */ 13616350Skarels send_delete() 13716350Skarels { 13816350Skarels 13916363Skarels msg.type = DELETE; 14016363Skarels /* 14116363Skarels * This is just a extra clean up, so just send it 14216363Skarels * and don't wait for an answer 14316363Skarels */ 14416363Skarels msg.id_num = remote_id; 14516363Skarels daemon_addr.sin_addr = his_machine_addr; 14616363Skarels if (sendto(ctl_sockt, &msg, sizeof(CTL_MSG), 0, &daemon_addr, 14716363Skarels sizeof(daemon_addr)) != sizeof(CTL_MSG)) 14816363Skarels perror("send_delete remote"); 14916363Skarels msg.id_num = local_id; 15016363Skarels daemon_addr.sin_addr = my_machine_addr; 15116363Skarels if (sendto(ctl_sockt, &msg, sizeof(CTL_MSG), 0, &daemon_addr, 15216363Skarels sizeof(daemon_addr)) != sizeof(CTL_MSG)) 15316363Skarels perror("send_delete local"); 15416350Skarels } 155