bump product version to 5.0.4.1
[LibreOffice.git] / sd / source / ui / remotecontrol / DiscoveryService.cxx
blob9ce33ae98e47e744549c4465dcf6969e1125aaa4
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 <comphelper/processfactory.hxx>
18 #include <rtl/strbuf.hxx>
19 #include <config_features.h>
21 #include "DiscoveryService.hxx"
23 #ifdef WIN32
24 // LO vs WinAPI conflict
25 #undef WB_LEFT
26 #undef WB_RIGHT
28 #include <winsock2.h>
29 #include <ws2tcpip.h>
31 #include "WINNetworkService.hxx"
32 typedef int socklen_t;
33 #else
34 #include <unistd.h>
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <netinet/in.h>
38 #include <arpa/inet.h>
39 #endif
41 #ifdef MACOSX
42 #include <osl/conditn.hxx>
43 #include <premac.h>
44 #import <CoreFoundation/CoreFoundation.h>
45 #include <postmac.h>
46 #import "OSXNetworkService.hxx"
47 #endif
49 #if HAVE_FEATURE_AVAHI
50 #include "AvahiNetworkService.hxx"
51 #endif
53 using namespace osl;
54 using namespace sd;
56 DiscoveryService::DiscoveryService()
57 : mSocket(-1)
58 , zService(0)
62 DiscoveryService::~DiscoveryService()
64 if (mSocket != -1)
66 #ifdef WNT
67 closesocket( mSocket );
68 #else
69 close( mSocket );
70 #endif
73 if (zService)
74 zService->clear();
77 void DiscoveryService::setupSockets()
80 #ifdef MACOSX
81 // Bonjour for OSX
82 zService = new OSXNetworkService();
83 #endif
85 #if HAVE_FEATURE_AVAHI
86 // Avahi for Linux
87 char hostname[1024];
88 hostname[1023] = '\0';
89 gethostname(hostname, 1023);
91 zService = new AvahiNetworkService(hostname);
92 #endif
94 #ifdef WIN32
95 zService = new WINNetworkService();
96 #endif
98 if (zService)
99 zService->setup();
101 // Old implementation for backward compatibility matter
102 mSocket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
103 if (mSocket == -1)
105 SAL_WARN("sd", "DiscoveryService: socket failed: " << errno);
106 return; // would be better to throw, but unsure if caller handles that
109 sockaddr_in aAddr;
110 memset(&aAddr, 0, sizeof(aAddr));
111 aAddr.sin_family = AF_INET;
112 aAddr.sin_addr.s_addr = htonl(INADDR_ANY);
113 aAddr.sin_port = htons( PORT_DISCOVERY );
115 int rc = bind( mSocket, reinterpret_cast<sockaddr*>(&aAddr), sizeof(sockaddr_in) );
117 if (rc)
119 SAL_WARN("sd", "DiscoveryService: bind failed: " << errno);
120 return; // would be better to throw, but unsure if caller handles that
123 struct ip_mreq multicastRequest;
125 // the Win32 SDK 8.1 deprecates inet_addr()
126 #if defined(_WIN32_WINNT) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
127 IN_ADDR addr;
128 OUString const saddr("239.0.0.1");
129 INT ret = InetPtonW(AF_INET, saddr.getStr(), & addr);
130 if (1 == ret)
132 multicastRequest.imr_multiaddr.s_addr = addr.S_un.S_addr;
134 #else
135 multicastRequest.imr_multiaddr.s_addr = inet_addr( "239.0.0.1" );
136 #endif
137 multicastRequest.imr_interface.s_addr = htonl(INADDR_ANY);
139 rc = setsockopt( mSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
140 #ifdef WNT
141 (const char*)
142 #endif
143 &multicastRequest, sizeof(multicastRequest));
145 if (rc)
147 SAL_WARN("sd", "DiscoveryService: setsockopt failed: " << errno);
148 return; // would be better to throw, but unsure if caller handles that
152 void SAL_CALL DiscoveryService::run()
154 osl::Thread::setName("DiscoveryService");
156 setupSockets();
158 // Kept for backwrad compatibility
159 char aBuffer[BUFFER_SIZE];
160 while ( true )
162 memset( aBuffer, 0, sizeof(char) * BUFFER_SIZE );
163 sockaddr_in aAddr;
164 socklen_t aLen = sizeof( aAddr );
165 if(recvfrom( mSocket, aBuffer, BUFFER_SIZE, 0, reinterpret_cast<sockaddr*>(&aAddr), &aLen ) > 0)
167 OString aString( aBuffer, strlen( "LOREMOTE_SEARCH" ) );
168 if ( aString == "LOREMOTE_SEARCH" )
170 OStringBuffer aStringBuffer("LOREMOTE_ADVERTISE\n");
171 aStringBuffer.append( OUStringToOString(
172 osl::SocketAddr::getLocalHostname(), RTL_TEXTENCODING_UTF8 ) )
173 .append( "\n\n" );
174 if ( sendto( mSocket, aStringBuffer.getStr(),
175 aStringBuffer.getLength(), 0, reinterpret_cast<sockaddr*>(&aAddr),
176 sizeof(aAddr) ) <= 0 )
178 // Write error or closed socket -- we are done.
179 return;
183 else
185 // Read error or closed socket -- we are done.
186 return;
191 DiscoveryService *sd::DiscoveryService::spService = NULL;
193 void DiscoveryService::setup()
195 if (spService)
196 return;
198 spService = new DiscoveryService();
199 spService->create();
202 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */