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