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