xref: /original-bsd/old/talk/talk/look_up.c (revision e58c8952)
1 /*-
2  * Copyright (c) 1983, 1985
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 /* from "@(#)look_up.c	5.1 (Berkeley) 6/6/85"; */
9 
10 #ifndef lint
11 static char sccsid[] = "@(#)look_up.c	6.4 (Berkeley) 04/02/94";
12 #endif not lint
13 
14 #include "talk_ctl.h"
15 
16 
17 /*
18  * See if the local daemon has a invitation for us
19  */
20 check_local()
21 {
22 	CTL_RESPONSE response;
23 
24 	/* the rest of msg was set up in get_names */
25 	msg.ctl_addr = ctl_addr;
26 	/* must be initiating a talk */
27 	if (!look_for_invite(&response))
28 		return (0);
29 	/*
30 	 * There was an invitation waiting for us,
31 	 * so connect with the other (hopefully waiting) party
32 	 */
33 	current_state = "Waiting to connect with caller";
34 again:
35 	swapresponse(&response);
36 	response.addr.sin_family = AF_INET;
37 	if (connect(sockt,
38 	    (struct sockaddr *)&response.addr, sizeof(response.addr)) != -1)
39 		return (1);
40 	if (errno == EINTR)
41 		goto again;
42 	if (errno == ECONNREFUSED) {
43 		/*
44 		 * The caller gave up, but his invitation somehow
45 		 * was not cleared. Clear it and initiate an
46 		 * invitation. (We know there are no newer invitations,
47 		 * the talkd works LIFO.)
48 		 */
49 		ctl_transact(his_machine_addr, msg, DELETE, &response);
50 		close(sockt);
51 		open_sockt();
52 		return (0);
53 	}
54 	p_error("Unable to connect with initiator");
55 	/*NOTREACHED*/
56 }
57 
58 /*
59  * Look for an invitation on 'machine'
60  */
61 look_for_invite(response)
62 	CTL_RESPONSE *response;
63 {
64 	struct in_addr machine_addr;
65 
66 	current_state = "Checking for invitation on caller's machine";
67 	ctl_transact(his_machine_addr, msg, LOOK_UP, response);
68 	/* the switch is for later options, such as multiple invitations */
69 	switch (response->answer) {
70 
71 	case SUCCESS:
72 		msg.id_num = response->id_num;
73 		return (1);
74 
75 	default :
76 		/* there wasn't an invitation waiting for us */
77 		return (0);
78 	}
79 }
80 
81 /*
82  * heuristic to detect if need to reshuffle CTL_RESPONSE structure
83  */
84 
85 #define swapshort(a) (((a << 8) | ((unsigned short) a >> 8)) & 0xffff)
86 #define swaplong(a) ((swapshort(a) << 16) | (swapshort(((unsigned)a >> 16))))
87 
88 #ifdef sun
89 struct ctl_response_vax {
90 	char type;
91 	char answer;
92 	short junk;
93 	int id_num;
94 	struct sockaddr_in addr;
95 };
96 
97 swapresponse(rsp)
98 	CTL_RESPONSE *rsp;
99 {
100 	struct ctl_response_vax swaprsp;
101 
102 	if (rsp->addr.sin_family != AF_INET) {
103 		bcopy(rsp, &swaprsp, sizeof(CTL_RESPONSE));
104 		swaprsp.addr.sin_family = swapshort(swaprsp.addr.sin_family);
105 		if (swaprsp.addr.sin_family == AF_INET) {
106 			rsp->addr = swaprsp.addr;
107 			rsp->type = swaprsp.type;
108 			rsp->answer = swaprsp.answer;
109 			rsp->id_num = swaplong(swaprsp.id_num);
110 		}
111 	}
112 }
113 #endif
114 
115 #ifdef vax
116 struct ctl_response_sun {
117 	char type;
118 	char answer;
119 	unsigned short id_num2;
120 	unsigned short id_num1;
121 	short sin_family;
122 	short sin_port;
123 	short sin_addr2;
124 	short sin_addr1;
125 };
126 
127 swapresponse(rsp)
128 	CTL_RESPONSE *rsp;
129 {
130 	struct ctl_response_sun swaprsp;
131 
132 	if (rsp->addr.sin_family != AF_INET) {
133 		bcopy(rsp, &swaprsp, sizeof(struct ctl_response_sun));
134 		if (swaprsp.sin_family == swapshort(AF_INET)) {
135 			rsp->type = swaprsp.type;
136 			rsp->answer = swaprsp.answer;
137 			rsp->id_num = swapshort(swaprsp.id_num1)
138 			    | (swapshort(swaprsp.id_num2) << 16);
139 			rsp->addr.sin_family = swapshort(swaprsp.sin_family);
140  			rsp->addr.sin_port = swaprsp.sin_port;
141 			rsp->addr.sin_addr.s_addr =
142 			    swaprsp.sin_addr2 | (swaprsp.sin_addr1 << 16);
143 		}
144 	}
145 }
146 #endif
147