LibreOffice Module sd (master) 1
DiscoveryService.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 */
9
10#include <errno.h>
11#include <string.h>
12#include <iostream>
13
14#include <osl/socket.hxx>
15#include <config_features.h>
16#include <sal/log.hxx>
17
18#include "DiscoveryService.hxx"
19#include "ZeroconfService.hxx"
20
21#ifdef _WIN32
22 // LO vs WinAPI conflict
23 #undef WB_LEFT
24 #undef WB_RIGHT
25
26 #include <winsock2.h>
27 #include <ws2tcpip.h>
28
29 #include "WINNetworkService.hxx"
30 typedef int socklen_t;
31#else
32 #include <unistd.h>
33 #include <sys/socket.h>
34 #include <netinet/in.h>
35#endif
36
37#ifdef MACOSX
38 #include <osl/conditn.hxx>
39 #include <premac.h>
40 #import <CoreFoundation/CoreFoundation.h>
41 #include <postmac.h>
42 #import "OSXNetworkService.hxx"
43#endif
44
45#if HAVE_FEATURE_AVAHI
47#endif
48
49using namespace osl;
50using namespace sd;
51
52DiscoveryService::DiscoveryService()
53 : mSocket(-1)
54 , zService(nullptr)
55{
56}
57
59{
60 if (mSocket != -1)
61 {
62#ifdef _WIN32
63 closesocket( mSocket );
64#else
65 close( mSocket );
66#endif
67 }
68
69 if (zService)
70 zService->clear();
71}
72
74{
75
76#ifdef MACOSX
77 // Bonjour for OSX
79 zService->setup();
80#endif
81
82#if HAVE_FEATURE_AVAHI
83 // Avahi for Linux
84 char hostname[1024];
85 hostname[1023] = '\0';
86 gethostname(hostname, 1023);
87
88 zService = new AvahiNetworkService(hostname);
89 zService->setup();
90#endif
91
92#ifdef _WIN32
94 zService->setup();
95#endif
96
97 // Old implementation for backward compatibility matter
98 mSocket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
99 if (mSocket == -1)
100 {
101 SAL_WARN("sd", "DiscoveryService: socket failed: " << errno);
102 return; // would be better to throw, but unsure if caller handles that
103 }
104
105 sockaddr_in aAddr = {};
106 aAddr.sin_family = AF_INET;
107 aAddr.sin_addr.s_addr = htonl(INADDR_ANY);
108 aAddr.sin_port = htons( PORT_DISCOVERY );
109
110 int rc = bind( mSocket, reinterpret_cast<sockaddr*>(&aAddr), sizeof(sockaddr_in) );
111
112 if (rc)
113 {
114 SAL_WARN("sd", "DiscoveryService: bind failed: " << errno);
115 return; // would be better to throw, but unsure if caller handles that
116 }
117
118 struct ip_mreq multicastRequest;
119
120 multicastRequest.imr_multiaddr.s_addr = htonl((239U << 24) | 1U); // 239.0.0.1
121 multicastRequest.imr_interface.s_addr = htonl(INADDR_ANY);
122
123 rc = setsockopt( mSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
124 #ifdef _WIN32
125 reinterpret_cast<const char*>(&multicastRequest),
126 #else
127 &multicastRequest,
128 #endif
129 sizeof(multicastRequest));
130
131 if (rc)
132 {
133 SAL_WARN("sd", "DiscoveryService: setsockopt failed: " << errno);
134 return; // would be better to throw, but unsure if caller handles that
135 }
136}
137
139{
140 osl::Thread::setName("DiscoveryService");
141
142 setupSockets();
143
144 // Kept for backward compatibility
145 while ( true )
146 {
147 char aBuffer[BUFFER_SIZE] = {};
148 sockaddr_in aAddr;
149 socklen_t aLen = sizeof( aAddr );
150 if(recvfrom( mSocket, aBuffer, BUFFER_SIZE, 0, reinterpret_cast<sockaddr*>(&aAddr), &aLen ) > 0)
151 {
152 OString aString( aBuffer, strlen( "LOREMOTE_SEARCH" ) );
153 if ( aString == "LOREMOTE_SEARCH" )
154 {
155 OString aStringBuffer = "LOREMOTE_ADVERTISE\n" +
156 OUStringToOString(osl::SocketAddr::getLocalHostname(), RTL_TEXTENCODING_UTF8 ) +
157 "\n\n";
158 if ( sendto( mSocket, aStringBuffer.getStr(),
159 aStringBuffer.getLength(), 0, reinterpret_cast<sockaddr*>(&aAddr),
160 sizeof(aAddr) ) <= 0 )
161 {
162 // Write error or closed socket -- we are done.
163 return;
164 }
165 }
166 }
167 else
168 {
169 // Read error or closed socket -- we are done.
170 return;
171 }
172 }
173}
174
176
178{
179 if (spService)
180 return;
181
183 spService->create();
184}
185
186/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define PORT_DISCOVERY
The port used by LO's custom remote server discovery protocol.
#define BUFFER_SIZE
virtual void SAL_CALL run() override
static DiscoveryService * spService
ZeroconfService * zService
virtual ~DiscoveryService() override
void setupSockets()
Networking related setup – must be run within our own thread to prevent the application blocking (fdo...
virtual void setup()=0
virtual void clear()=0
bool close
#define SAL_WARN(area, stream)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
sal_uInt32 htonl(sal_uInt32 h)
sal_uInt16 htons(sal_uInt16 h)
std::unique_ptr< char[]> aBuffer