1 /* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)ctl_transact.c 8.1 (Berkeley) 06/06/93"; 10 #endif /* not lint */ 11 12 #include <sys/types.h> 13 #include <sys/socket.h> 14 #include <sys/time.h> 15 #include <netinet/in.h> 16 #include <protocols/talkd.h> 17 #include <errno.h> 18 #include "talk_ctl.h" 19 20 #define CTL_WAIT 2 /* time to wait for a response, in seconds */ 21 22 /* 23 * SOCKDGRAM is unreliable, so we must repeat messages if we have 24 * not recieved an acknowledgement within a reasonable amount 25 * of time 26 */ 27 ctl_transact(target, msg, type, rp) 28 struct in_addr target; 29 CTL_MSG msg; 30 int type; 31 CTL_RESPONSE *rp; 32 { 33 int read_mask, ctl_mask, nready, cc; 34 struct timeval wait; 35 36 msg.type = type; 37 daemon_addr.sin_addr = target; 38 daemon_addr.sin_port = daemon_port; 39 ctl_mask = 1 << ctl_sockt; 40 41 /* 42 * Keep sending the message until a response of 43 * the proper type is obtained. 44 */ 45 do { 46 wait.tv_sec = CTL_WAIT; 47 wait.tv_usec = 0; 48 /* resend message until a response is obtained */ 49 do { 50 cc = sendto(ctl_sockt, (char *)&msg, sizeof (msg), 0, 51 (struct sockaddr *)&daemon_addr, 52 sizeof (daemon_addr)); 53 if (cc != sizeof (msg)) { 54 if (errno == EINTR) 55 continue; 56 p_error("Error on write to talk daemon"); 57 } 58 read_mask = ctl_mask; 59 nready = select(32, &read_mask, 0, 0, &wait); 60 if (nready < 0) { 61 if (errno == EINTR) 62 continue; 63 p_error("Error waiting for daemon response"); 64 } 65 } while (nready == 0); 66 /* 67 * Keep reading while there are queued messages 68 * (this is not necessary, it just saves extra 69 * request/acknowledgements being sent) 70 */ 71 do { 72 cc = recv(ctl_sockt, (char *)rp, sizeof (*rp), 0); 73 if (cc < 0) { 74 if (errno == EINTR) 75 continue; 76 p_error("Error on read from talk daemon"); 77 } 78 read_mask = ctl_mask; 79 /* an immediate poll */ 80 timerclear(&wait); 81 nready = select(32, &read_mask, 0, 0, &wait); 82 } while (nready > 0 && (rp->vers != TALK_VERSION || 83 rp->type != type)); 84 } while (rp->vers != TALK_VERSION || rp->type != type); 85 rp->id_num = ntohl(rp->id_num); 86 rp->addr.sa_family = ntohs(rp->addr.sa_family); 87 } 88