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 sd;
55 :
56 0 : DiscoveryService::DiscoveryService()
57 : : mSocket(-1)
58 0 : , zService(0)
59 : {
60 0 : }
61 :
62 0 : DiscoveryService::~DiscoveryService()
63 : {
64 0 : if (mSocket != -1)
65 : {
66 : #ifdef WNT
67 : closesocket( mSocket );
68 : #else
69 0 : close( mSocket );
70 : #endif
71 : }
72 :
73 0 : if (zService)
74 0 : zService->clear();
75 0 : }
76 :
77 0 : void DiscoveryService::setupSockets()
78 : {
79 :
80 : #ifdef MACOSX
81 : // Bonjour for OSX
82 : zService = new OSXNetworkService();
83 : #endif
84 :
85 : #if HAVE_FEATURE_AVAHI
86 : // Avahi for Linux
87 : char hostname[1024];
88 : hostname[1023] = '\0';
89 : gethostname(hostname, 1023);
90 :
91 : zService = new AvahiNetworkService(hostname);
92 : #endif
93 :
94 : #ifdef WIN32
95 : zService = new WINNetworkService();
96 : #endif
97 :
98 0 : if (zService)
99 0 : zService->setup();
100 :
101 : // Old implementation for backward compatibility matter
102 0 : mSocket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
103 0 : if (mSocket == -1)
104 : {
105 : SAL_WARN("sd", "DiscoveryService: socket failed: " << errno);
106 0 : return; // would be better to throw, but unsure if caller handles that
107 : }
108 :
109 : sockaddr_in aAddr;
110 0 : memset(&aAddr, 0, sizeof(aAddr));
111 0 : aAddr.sin_family = AF_INET;
112 0 : aAddr.sin_addr.s_addr = htonl(INADDR_ANY);
113 0 : aAddr.sin_port = htons( PORT_DISCOVERY );
114 :
115 0 : int rc = bind( mSocket, (sockaddr*) &aAddr, sizeof(sockaddr_in) );
116 :
117 0 : if (rc)
118 : {
119 : SAL_WARN("sd", "DiscoveryService: bind failed: " << errno);
120 0 : return; // would be better to throw, but unsure if caller handles that
121 : }
122 :
123 : struct ip_mreq multicastRequest;
124 :
125 0 : multicastRequest.imr_multiaddr.s_addr = inet_addr( "239.0.0.1" );
126 0 : multicastRequest.imr_interface.s_addr = htonl(INADDR_ANY);
127 :
128 : rc = setsockopt( mSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
129 : #ifdef WNT
130 : (const char*)
131 : #endif
132 0 : &multicastRequest, sizeof(multicastRequest));
133 :
134 0 : if (rc)
135 : {
136 : SAL_WARN("sd", "DiscoveryService: setsockopt failed: " << errno);
137 0 : return; // would be better to throw, but unsure if caller handles that
138 : }
139 : }
140 :
141 0 : void SAL_CALL DiscoveryService::run()
142 : {
143 0 : osl::Thread::setName("DiscoveryService");
144 :
145 0 : setupSockets();
146 :
147 : // Kept for backwrad compatibility
148 : char aBuffer[BUFFER_SIZE];
149 : while ( true )
150 : {
151 0 : memset( aBuffer, 0, sizeof(char) * BUFFER_SIZE );
152 : sockaddr_in aAddr;
153 0 : socklen_t aLen = sizeof( aAddr );
154 0 : if(recvfrom( mSocket, aBuffer, BUFFER_SIZE, 0, (sockaddr*) &aAddr, &aLen ) > 0)
155 : {
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 : // Write error or closed socket -- we are done.
168 0 : return;
169 0 : }
170 0 : }
171 : }
172 : else
173 : {
174 : // Read error or closed socket -- we are done.
175 0 : return;
176 : }
177 0 : }
178 : }
179 :
180 : DiscoveryService *sd::DiscoveryService::spService = NULL;
181 :
182 0 : void DiscoveryService::setup()
183 : {
184 0 : if (spService)
185 0 : return;
186 :
187 0 : spService = new DiscoveryService();
188 0 : spService->create();
189 114 : }
190 :
191 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|