1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
17 #include <rtl/strbuf.hxx>
18 #include <osl/socket.hxx>
19 #include <config_features.h>
20 #include <sal/log.hxx>
22 #include "DiscoveryService.hxx"
23 #include "ZeroconfService.hxx"
26 // LO vs WinAPI conflict
33 #include "WINNetworkService.hxx"
34 typedef int socklen_t
;
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
44 #include <osl/conditn.hxx>
46 #import <CoreFoundation/CoreFoundation.h>
48 #import "OSXNetworkService.hxx"
51 #if HAVE_FEATURE_AVAHI
52 #include "AvahiNetworkService.hxx"
58 DiscoveryService::DiscoveryService()
64 DiscoveryService::~DiscoveryService()
69 closesocket( mSocket
);
79 void DiscoveryService::setupSockets()
84 zService
= new OSXNetworkService();
88 #if HAVE_FEATURE_AVAHI
91 hostname
[1023] = '\0';
92 gethostname(hostname
, 1023);
94 zService
= new AvahiNetworkService(hostname
);
99 zService
= new WINNetworkService();
103 // Old implementation for backward compatibility matter
104 mSocket
= socket( AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
107 SAL_WARN("sd", "DiscoveryService: socket failed: " << errno
);
108 return; // would be better to throw, but unsure if caller handles that
112 memset(&aAddr
, 0, sizeof(aAddr
));
113 aAddr
.sin_family
= AF_INET
;
114 aAddr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
115 aAddr
.sin_port
= htons( PORT_DISCOVERY
);
117 int rc
= bind( mSocket
, reinterpret_cast<sockaddr
*>(&aAddr
), sizeof(sockaddr_in
) );
121 SAL_WARN("sd", "DiscoveryService: bind failed: " << errno
);
122 return; // would be better to throw, but unsure if caller handles that
125 struct ip_mreq multicastRequest
;
127 // the Win32 SDK 8.1 deprecates inet_addr()
130 INT ret
= InetPtonW(AF_INET
, L
"239.0.0.1", & addr
);
133 multicastRequest
.imr_multiaddr
.s_addr
= addr
.S_un
.S_addr
;
136 multicastRequest
.imr_multiaddr
.s_addr
= inet_addr( "239.0.0.1" );
138 multicastRequest
.imr_interface
.s_addr
= htonl(INADDR_ANY
);
140 rc
= setsockopt( mSocket
, IPPROTO_IP
, IP_ADD_MEMBERSHIP
,
142 reinterpret_cast<const char*>(&multicastRequest
),
146 sizeof(multicastRequest
));
150 SAL_WARN("sd", "DiscoveryService: setsockopt failed: " << errno
);
151 return; // would be better to throw, but unsure if caller handles that
155 void SAL_CALL
DiscoveryService::run()
157 osl::Thread::setName("DiscoveryService");
161 // Kept for backward compatibility
162 char aBuffer
[BUFFER_SIZE
];
165 memset( aBuffer
, 0, sizeof(char) * BUFFER_SIZE
);
167 socklen_t aLen
= sizeof( aAddr
);
168 if(recvfrom( mSocket
, aBuffer
, BUFFER_SIZE
, 0, reinterpret_cast<sockaddr
*>(&aAddr
), &aLen
) > 0)
170 OString
aString( aBuffer
, strlen( "LOREMOTE_SEARCH" ) );
171 if ( aString
== "LOREMOTE_SEARCH" )
173 OStringBuffer
aStringBuffer("LOREMOTE_ADVERTISE\n");
174 aStringBuffer
.append( OUStringToOString(
175 osl::SocketAddr::getLocalHostname(), RTL_TEXTENCODING_UTF8
) )
177 if ( sendto( mSocket
, aStringBuffer
.getStr(),
178 aStringBuffer
.getLength(), 0, reinterpret_cast<sockaddr
*>(&aAddr
),
179 sizeof(aAddr
) ) <= 0 )
181 // Write error or closed socket -- we are done.
188 // Read error or closed socket -- we are done.
194 DiscoveryService
*sd::DiscoveryService::spService
= nullptr;
196 void DiscoveryService::setup()
201 spService
= new DiscoveryService();
205 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */