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