1 // -*- Mode: C++; -*-
2 // Package : omniORB
3 // unixAddress.cc Created on: 6 Aug 2001
4 // Author : Sai Lai Lo (sll)
5 //
6 // Copyright (C) 2006-2013 Apasphere Ltd
7 // Copyright (C) 2001 AT&T Laboratories Cambridge
8 //
9 // This file is part of the omniORB library
10 //
11 // The omniORB library is free software; you can redistribute it and/or
12 // modify it under the terms of the GNU Lesser General Public
13 // License as published by the Free Software Foundation; either
14 // version 2.1 of the License, or (at your option) any later version.
15 //
16 // This library is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 // Lesser General Public License for more details.
20 //
21 // You should have received a copy of the GNU Lesser General Public
22 // License along with this library. If not, see http://www.gnu.org/licenses/
23 //
24 //
25 // Description:
26 // *** PROPRIETARY INTERFACE ***
27 //
28
29 #include <omniORB4/CORBA.h>
30 #include <omniORB4/giopEndpoint.h>
31 #include <unix/unixConnection.h>
32 #include <unix/unixAddress.h>
33 #include <stdio.h>
34 #include <omniORB4/linkHacks.h>
35 #include <sys/un.h>
36
37 #if defined(USE_FAKE_INTERRUPTABLE_RECV)
38 # include <orbParameters.h>
39 #endif
40
41 OMNI_EXPORT_LINK_FORCE_SYMBOL(unixAddress);
42
43 #ifndef AF_LOCAL
44 # ifdef AF_UNIX
45 # define AF_LOCAL AF_UNIX
46 # endif
47 #endif
48
OMNI_NAMESPACE_BEGIN(omni)49 OMNI_NAMESPACE_BEGIN(omni)
50
51 /////////////////////////////////////////////////////////////////////////
52 unixAddress::unixAddress(const char* filename) {
53
54 pd_filename = (const char*) filename;
55 pd_address_string = unixConnection::unToString(filename);
56 }
57
58 /////////////////////////////////////////////////////////////////////////
59 const char*
type() const60 unixAddress::type() const {
61 return "giop:unix";
62 }
63
64 /////////////////////////////////////////////////////////////////////////
65 const char*
address() const66 unixAddress::address() const {
67 return pd_address_string;
68 }
69
70 /////////////////////////////////////////////////////////////////////////
71 giopAddress*
duplicate() const72 unixAddress::duplicate() const {
73 return new unixAddress(pd_filename);
74 }
75
76 /////////////////////////////////////////////////////////////////////////
77 giopActiveConnection*
Connect(const omni_time_t & deadline,CORBA::ULong strand_flags,CORBA::Boolean & timed_out) const78 unixAddress::Connect(const omni_time_t& deadline,
79 CORBA::ULong strand_flags,
80 CORBA::Boolean& timed_out) const {
81
82 struct sockaddr_un raddr;
83 int rc;
84 SocketHandle_t sock;
85
86 if ((sock = socket(AF_LOCAL,SOCK_STREAM,0)) == RC_INVALID_SOCKET) {
87 return 0;
88 }
89
90 memset((void*)&raddr, 0, sizeof(raddr));
91 raddr.sun_family = AF_LOCAL;
92 strncpy(raddr.sun_path, pd_filename, sizeof(raddr.sun_path) - 1);
93
94 #if !defined(USE_NONBLOCKING_CONNECT)
95
96 if (::connect(sock, (struct sockaddr *)&raddr,
97 sizeof(raddr)) == RC_SOCKET_ERROR) {
98
99 omniORB::logs(25, "Failed to connect to Unix socket.");
100 CLOSESOCKET(sock);
101 return 0;
102 }
103
104 #else
105
106 if (tcpSocket::setNonBlocking(sock) == RC_INVALID_SOCKET) {
107 omniORB::logs(25, "Failed to set Unix socket to non-blocking mode.");
108 CLOSESOCKET(sock);
109 return 0;
110 }
111
112 if (::connect(sock,(struct sockaddr *)&raddr,
113 sizeof(raddr)) == RC_SOCKET_ERROR) {
114
115 int err = ERRNO;
116 if (err && err != RC_EINPROGRESS) {
117 omniORB::logs(25, "Failed to connect to Unix socket.");
118 CLOSESOCKET(sock);
119 return 0;
120 }
121 }
122
123 struct timeval t;
124
125 do {
126 if (tcpSocket::setAndCheckTimeout(deadline, t)) {
127 // Already timed out
128 omniORB::logs(25, "Timed out connecting to Unix socket.");
129 CLOSESOCKET(sock);
130 timed_out = 1;
131 return 0;
132 }
133
134 rc = tcpSocket::waitWrite(sock, t);
135
136 if (rc == 0) {
137 // Timed out
138 #if defined(USE_FAKE_INTERRUPTABLE_RECV)
139 continue;
140 #else
141 omniORB::logs(25, "Timed out connecting to Unix socket.");
142 CLOSESOCKET(sock);
143 timed_out = 1;
144 return 0;
145 #endif
146 }
147 else if (rc == RC_SOCKET_ERROR) {
148 if (ERRNO == RC_EINTR) {
149 continue;
150 }
151 else {
152 omniORB::logs(25, "Failed to connect to Unix socket "
153 "(waiting for writable socket)");
154 CLOSESOCKET(sock);
155 return 0;
156 }
157 }
158
159 // Check to make sure that the socket is connected.
160 OMNI_SOCKADDR_STORAGE peer;
161 SOCKNAME_SIZE_T len = sizeof(peer);
162 rc = getpeername(sock, (struct sockaddr*)&peer, &len);
163
164 if (rc == RC_SOCKET_ERROR) {
165 if (ERRNO == RC_EINTR) {
166 continue;
167 }
168 else {
169 omniORB::logs(25, "Failed to connect to Unix socket (no peer name).");
170 CLOSESOCKET(sock);
171 return 0;
172 }
173 }
174 break;
175
176 } while (1);
177 #endif
178
179 if (tcpSocket::setBlocking(sock) == RC_INVALID_SOCKET) {
180 omniORB::logs(25, "Failed to set Unix socket to blocking mode");
181 CLOSESOCKET(sock);
182 return 0;
183 }
184 return new unixActiveConnection(sock, pd_filename);
185 }
186
187 /////////////////////////////////////////////////////////////////////////
188 CORBA::Boolean
Poke() const189 unixAddress::Poke() const {
190
191 struct sockaddr_un raddr;
192 int rc;
193 SocketHandle_t sock;
194
195 if ((sock = socket(AF_LOCAL,SOCK_STREAM,0)) == RC_INVALID_SOCKET) {
196 return 0;
197 }
198
199 memset((void*)&raddr,0,sizeof(raddr));
200 raddr.sun_family = AF_LOCAL;
201 strncpy(raddr.sun_path, pd_filename, sizeof(raddr.sun_path) - 1);
202
203
204 #if defined(USE_NONBLOCKING_CONNECT)
205
206 if (tcpSocket::setNonBlocking(sock) == RC_INVALID_SOCKET) {
207 CLOSESOCKET(sock);
208 return 0;
209 }
210
211 #endif
212
213 if (::connect(sock,(struct sockaddr *)&raddr,
214 sizeof(raddr)) == RC_SOCKET_ERROR) {
215
216 if (ERRNO != RC_EINPROGRESS) {
217 CLOSESOCKET(sock);
218 return 0;
219 }
220 }
221
222 // The connect has not necessarily completed by this stage, but
223 // we've done enough to poke the endpoint.
224 CLOSESOCKET(sock);
225 return 1;
226 }
227
228
229 OMNI_NAMESPACE_END(omni)
230