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 :
16 : #include <comphelper/processfactory.hxx>
17 : #include <rtl/strbuf.hxx>
18 :
19 : #include "DiscoveryService.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 : typedef int socklen_t;
29 : #else
30 : #include <sys/types.h>
31 : #include <sys/socket.h>
32 : #include <netinet/in.h>
33 : #include <arpa/inet.h>
34 : #endif
35 :
36 : using namespace osl;
37 : using namespace rtl;
38 : using namespace sd;
39 :
40 0 : DiscoveryService::DiscoveryService() :
41 0 : mSocket(0)
42 : {
43 : int rc;
44 :
45 0 : mSocket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
46 :
47 : sockaddr_in aAddr;
48 0 : aAddr.sin_family = AF_INET;
49 0 : aAddr.sin_addr.s_addr = htonl(INADDR_ANY);
50 0 : aAddr.sin_port = htons( PORT_DISCOVERY );
51 :
52 0 : rc = bind( mSocket, (sockaddr*) &aAddr, sizeof(sockaddr_in) );
53 :
54 0 : if (rc)
55 : {
56 : SAL_WARN("sd", "DiscoveryService: bind failed: " << errno);
57 : return; // would be better to throw, but unsure if caller handles that
58 : }
59 :
60 : struct ip_mreq multicastRequest;
61 :
62 0 : multicastRequest.imr_multiaddr.s_addr = inet_addr( "239.0.0.1" );
63 0 : multicastRequest.imr_interface.s_addr = htonl(INADDR_ANY);
64 :
65 : rc = setsockopt( mSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
66 : #ifdef WNT
67 : (const char*)
68 : #endif
69 0 : &multicastRequest, sizeof(multicastRequest));
70 :
71 0 : if (rc)
72 : {
73 : SAL_WARN("sd", "DiscoveryService: setsockopt failed: " << errno);
74 : return; // would be better to throw, but unsure if caller handles that
75 : }
76 : }
77 :
78 0 : DiscoveryService::~DiscoveryService()
79 : {
80 0 : }
81 :
82 0 : void SAL_CALL DiscoveryService::run()
83 : {
84 : char aBuffer[BUFFER_SIZE];
85 0 : while ( true )
86 : {
87 0 : memset( aBuffer, 0, sizeof(char) * BUFFER_SIZE );
88 : sockaddr_in aAddr;
89 0 : socklen_t aLen = sizeof( aAddr );
90 0 : recvfrom( mSocket, aBuffer, BUFFER_SIZE, 0, (sockaddr*) &aAddr, &aLen );
91 0 : OString aString( aBuffer, strlen( "LOREMOTE_SEARCH" ) );
92 0 : if ( aString.compareTo( "LOREMOTE_SEARCH" ) == 0 )
93 : {
94 0 : OStringBuffer aStringBuffer("LOREMOTE_ADVERTISE\n");
95 : aStringBuffer.append( OUStringToOString(
96 0 : osl::SocketAddr::getLocalHostname(), RTL_TEXTENCODING_UTF8 ) )
97 0 : .append( "\n\n" );
98 0 : if ( sendto( mSocket, aStringBuffer.getStr(),
99 0 : aStringBuffer.getLength(), 0, (sockaddr*) &aAddr,
100 0 : sizeof(aAddr) ) <= 0 )
101 : {
102 : // Read error or closed socket -- we are done.
103 0 : return;
104 0 : }
105 : }
106 0 : }
107 : }
108 :
109 : DiscoveryService *sd::DiscoveryService::spService = NULL;
110 :
111 0 : void DiscoveryService::setup()
112 : {
113 0 : if (spService)
114 0 : return;
115 :
116 0 : spService = new DiscoveryService();
117 0 : spService->create();
118 : }
119 :
120 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|