xref: /original-bsd/old/talk/talk/look_up.c (revision 6849621a)
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.3 (Berkeley) 10/17/92";
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,
37 	    (struct sockaddr *)&response.addr, sizeof(response.addr)) != -1)
38 		return (1);
39 	if (errno == EINTR)
40 		goto again;
41 	if (errno == ECONNREFUSED) {
42 		/*
43 		 * The caller gave up, but his invitation somehow
44 		 * was not cleared. Clear it and initiate an
45 		 * invitation. (We know there are no newer invitations,
46 		 * the talkd works LIFO.)
47 		 */
48 		ctl_transact(his_machine_addr, msg, DELETE, &response);
49 		close(sockt);
50 		open_sockt();
51 		return (0);
52 	}
53 	p_error("Unable to connect with initiator");
54 	/*NOTREACHED*/
55 }
56 
57 /*
58  * Look for an invitation on 'machine'
59  */
60 look_for_invite(response)
61 	CTL_RESPONSE *response;
62 {
63 	struct in_addr machine_addr;
64 
65 	current_state = "Checking for invitation on caller's machine";
66 	ctl_transact(his_machine_addr, msg, LOOK_UP, response);
67 	/* the switch is for later options, such as multiple invitations */
68 	switch (response->answer) {
69 
70 	case SUCCESS:
71 		msg.id_num = response->id_num;
72 		return (1);
73 
74 	default :
75 		/* there wasn't an invitation waiting for us */
76 		return (0);
77 	}
78 }
79 
80 /*
81  * heuristic to detect if need to reshuffle CTL_RESPONSE structure
82  */
83 
84 #define swapshort(a) (((a << 8) | ((unsigned short) a >> 8)) & 0xffff)
85 #define swaplong(a) ((swapshort(a) << 16) | (swapshort(((unsigned)a >> 16))))
86 
87 #ifdef sun
88 struct ctl_response_vax {
89 	char type;
90 	char answer;
91 	short junk;
92 	int id_num;
93 	struct sockaddr_in addr;
94 };
95 
96 swapresponse(rsp)
97 	CTL_RESPONSE *rsp;
98 {
99 	struct ctl_response_vax swaprsp;
100 
101 	if (rsp->addr.sin_family != AF_INET) {
102 		bcopy(rsp, &swaprsp, sizeof(CTL_RESPONSE));
103 		swaprsp.addr.sin_family = swapshort(swaprsp.addr.sin_family);
104 		if (swaprsp.addr.sin_family == AF_INET) {
105 			rsp->addr = swaprsp.addr;
106 			rsp->type = swaprsp.type;
107 			rsp->answer = swaprsp.answer;
108 			rsp->id_num = swaplong(swaprsp.id_num);
109 		}
110 	}
111 }
112 #endif
113 
114 #ifdef vax
115 struct ctl_response_sun {
116 	char type;
117 	char answer;
118 	unsigned short id_num2;
119 	unsigned short id_num1;
120 	short sin_family;
121 	short sin_port;
122 	short sin_addr2;
123 	short sin_addr1;
124 };
125 
126 swapresponse(rsp)
127 	CTL_RESPONSE *rsp;
128 {
129 	struct ctl_response_sun swaprsp;
130 
131 	if (rsp->addr.sin_family != AF_INET) {
132 		bcopy(rsp, &swaprsp, sizeof(struct ctl_response_sun));
133 		if (swaprsp.sin_family == swapshort(AF_INET)) {
134 			rsp->type = swaprsp.type;
135 			rsp->answer = swaprsp.answer;
136 			rsp->id_num = swapshort(swaprsp.id_num1)
137 			    | (swapshort(swaprsp.id_num2) << 16);
138 			rsp->addr.sin_family = swapshort(swaprsp.sin_family);
139  			rsp->addr.sin_port = swaprsp.sin_port;
140 			rsp->addr.sin_addr.s_addr =
141 			    swaprsp.sin_addr2 | (swaprsp.sin_addr1 << 16);
142 		}
143 	}
144 }
145 #endif
146