Line data Source code
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 <stdlib.h>
12 : #include <string.h>
13 : #include <algorithm>
14 : #include <vector>
15 : #include <iostream>
16 :
17 : #include <comphelper/processfactory.hxx>
18 : #include <rtl/strbuf.hxx>
19 : #include <config_features.h>
20 :
21 : #include "DiscoveryService.hxx"
22 :
23 : #ifdef WIN32
24 : // LO vs WinAPI conflict
25 : #undef WB_LEFT
26 : #undef WB_RIGHT
27 :
28 : #include <winsock2.h>
29 : #include <ws2tcpip.h>
30 :
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
40 :
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
48 :
49 : #if HAVE_FEATURE_AVAHI
50 : #include "AvahiNetworkService.hxx"
51 : #endif
52 :
53 : using namespace osl;
54 : using namespace rtl;
55 : using namespace sd;
56 :
57 0 : DiscoveryService::DiscoveryService()
58 : : mSocket(-1)
59 0 : , zService(0)
60 : {
61 0 : }
62 :
63 0 : DiscoveryService::~DiscoveryService()
64 : {
65 0 : if (mSocket != -1)
66 : {
67 : #ifdef WNT
68 : closesocket( mSocket );
69 : #else
70 0 : close( mSocket );
71 : #endif
72 : }
73 :
74 0 : if (zService)
75 0 : zService->clear();
76 0 : }
77 :
78 0 : void DiscoveryService::setupSockets()
79 : {
80 :
81 : #ifdef MACOSX
82 : // Bonjour for OSX
83 : zService = new OSXNetworkService();
84 : #endif
85 :
86 : #if HAVE_FEATURE_AVAHI
87 : // Avahi for Linux
88 : char hostname[1024];
89 : hostname[1023] = '\0';
90 : gethostname(hostname, 1023);
91 :
92 : zService = new AvahiNetworkService(hostname);
93 : #endif
94 :
95 : #ifdef WIN32
96 : zService = new WINNetworkService();
97 : #endif
98 :
99 0 : if (zService)
100 0 : zService->setup();
101 :
102 : // Old implementation for backward compatibility matter
103 0 : mSocket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
104 0 : if (mSocket == -1)
105 : {
106 : SAL_WARN("sd", "DiscoveryService: socket failed: " << errno);
107 0 : return; // would be better to throw, but unsure if caller handles that
108 : }
109 :
110 : sockaddr_in aAddr;
111 0 : memset(&aAddr, 0, sizeof(aAddr));
112 0 : aAddr.sin_family = AF_INET;
113 0 : aAddr.sin_addr.s_addr = htonl(INADDR_ANY);
114 0 : aAddr.sin_port = htons( PORT_DISCOVERY );
115 :
116 0 : int rc = bind( mSocket, (sockaddr*) &aAddr, sizeof(sockaddr_in) );
117 :
118 0 : if (rc)
119 : {
120 : SAL_WARN("sd", "DiscoveryService: bind failed: " << errno);
121 0 : return; // would be better to throw, but unsure if caller handles that
122 : }
123 :
124 : struct ip_mreq multicastRequest;
125 :
126 0 : multicastRequest.imr_multiaddr.s_addr = inet_addr( "239.0.0.1" );
127 0 : multicastRequest.imr_interface.s_addr = htonl(INADDR_ANY);
128 :
129 : rc = setsockopt( mSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
130 : #ifdef WNT
131 : (const char*)
132 : #endif
133 0 : &multicastRequest, sizeof(multicastRequest));
134 :
135 0 : if (rc)
136 : {
137 : SAL_WARN("sd", "DiscoveryService: setsockopt failed: " << errno);
138 0 : return; // would be better to throw, but unsure if caller handles that
139 : }
140 : }
141 :
142 0 : void SAL_CALL DiscoveryService::run()
143 : {
144 0 : osl::Thread::setName("DiscoveryService");
145 :
146 0 : setupSockets();
147 :
148 : // Kept for backwrad compatibility
149 : char aBuffer[BUFFER_SIZE];
150 : while ( true )
151 : {
152 0 : memset( aBuffer, 0, sizeof(char) * BUFFER_SIZE );
153 : sockaddr_in aAddr;
154 0 : socklen_t aLen = sizeof( aAddr );
155 0 : recvfrom( mSocket, aBuffer, BUFFER_SIZE, 0, (sockaddr*) &aAddr, &aLen );
156 0 : OString aString( aBuffer, strlen( "LOREMOTE_SEARCH" ) );
157 0 : if ( aString == "LOREMOTE_SEARCH" )
158 : {
159 0 : OStringBuffer aStringBuffer("LOREMOTE_ADVERTISE\n");
160 : aStringBuffer.append( OUStringToOString(
161 0 : osl::SocketAddr::getLocalHostname(), RTL_TEXTENCODING_UTF8 ) )
162 0 : .append( "\n\n" );
163 0 : if ( sendto( mSocket, aStringBuffer.getStr(),
164 0 : aStringBuffer.getLength(), 0, (sockaddr*) &aAddr,
165 0 : sizeof(aAddr) ) <= 0 )
166 : {
167 : // Read error or closed socket -- we are done.
168 0 : return;
169 0 : }
170 : }
171 0 : }
172 : }
173 :
174 : DiscoveryService *sd::DiscoveryService::spService = NULL;
175 :
176 0 : void DiscoveryService::setup()
177 : {
178 0 : if (spService)
179 0 : return;
180 :
181 0 : spService = new DiscoveryService();
182 0 : spService->create();
183 0 : }
184 :
185 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|