bump product version to 6.3.0.0.beta1
[LibreOffice.git] / sd / source / ui / remotecontrol / DiscoveryService.cxx
bloba0067eaa14a6c40d60b7f58cbd43afff9b48bde5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
10 #include <errno.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <algorithm>
14 #include <vector>
15 #include <iostream>
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"
25 #ifdef _WIN32
26 // LO vs WinAPI conflict
27 #undef WB_LEFT
28 #undef WB_RIGHT
30 #include <winsock2.h>
31 #include <ws2tcpip.h>
33 #include "WINNetworkService.hxx"
34 typedef int socklen_t;
35 #else
36 #include <unistd.h>
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
41 #endif
43 #ifdef MACOSX
44 #include <osl/conditn.hxx>
45 #include <premac.h>
46 #import <CoreFoundation/CoreFoundation.h>
47 #include <postmac.h>
48 #import "OSXNetworkService.hxx"
49 #endif
51 #if HAVE_FEATURE_AVAHI
52 #include "AvahiNetworkService.hxx"
53 #endif
55 using namespace osl;
56 using namespace sd;
58 DiscoveryService::DiscoveryService()
59 : mSocket(-1)
60 , zService(nullptr)
64 DiscoveryService::~DiscoveryService()
66 if (mSocket != -1)
68 #ifdef _WIN32
69 closesocket( mSocket );
70 #else
71 close( mSocket );
72 #endif
75 if (zService)
76 zService->clear();
79 void DiscoveryService::setupSockets()
82 #ifdef MACOSX
83 // Bonjour for OSX
84 zService = new OSXNetworkService();
85 zService->setup();
86 #endif
88 #if HAVE_FEATURE_AVAHI
89 // Avahi for Linux
90 char hostname[1024];
91 hostname[1023] = '\0';
92 gethostname(hostname, 1023);
94 zService = new AvahiNetworkService(hostname);
95 zService->setup();
96 #endif
98 #ifdef _WIN32
99 zService = new WINNetworkService();
100 zService->setup();
101 #endif
103 // Old implementation for backward compatibility matter
104 mSocket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
105 if (mSocket == -1)
107 SAL_WARN("sd", "DiscoveryService: socket failed: " << errno);
108 return; // would be better to throw, but unsure if caller handles that
111 sockaddr_in aAddr;
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) );
119 if (rc)
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()
128 #if defined(_WIN32)
129 IN_ADDR addr;
130 INT ret = InetPtonW(AF_INET, L"239.0.0.1", & addr);
131 if (1 == ret)
133 multicastRequest.imr_multiaddr.s_addr = addr.S_un.S_addr;
135 #else
136 multicastRequest.imr_multiaddr.s_addr = inet_addr( "239.0.0.1" );
137 #endif
138 multicastRequest.imr_interface.s_addr = htonl(INADDR_ANY);
140 rc = setsockopt( mSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
141 #ifdef _WIN32
142 reinterpret_cast<const char*>(&multicastRequest),
143 #else
144 &multicastRequest,
145 #endif
146 sizeof(multicastRequest));
148 if (rc)
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");
159 setupSockets();
161 // Kept for backward compatibility
162 char aBuffer[BUFFER_SIZE];
163 while ( true )
165 memset( aBuffer, 0, sizeof(char) * BUFFER_SIZE );
166 sockaddr_in aAddr;
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 ) )
176 .append( "\n\n" );
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.
182 return;
186 else
188 // Read error or closed socket -- we are done.
189 return;
194 DiscoveryService *sd::DiscoveryService::spService = nullptr;
196 void DiscoveryService::setup()
198 if (spService)
199 return;
201 spService = new DiscoveryService();
202 spService->create();
205 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */