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