Coverage Report

Created: 2026-11-06 11:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/io/source/acceptor/acceptor.cxx
Line
Count
Source
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
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include <cppuhelper/implbase.hxx>
21
#include <cppuhelper/supportsservice.hxx>
22
#include <cppuhelper/unourl.hxx>
23
#include <rtl/malformeduriexception.hxx>
24
25
#include <com/sun/star/connection/AlreadyAcceptingException.hpp>
26
#include <com/sun/star/connection/ConnectionSetupException.hpp>
27
#include <com/sun/star/connection/XAcceptor.hpp>
28
#include <com/sun/star/lang/IllegalArgumentException.hpp>
29
#include <com/sun/star/lang/XServiceInfo.hpp>
30
#include <com/sun/star/uno/XComponentContext.hpp>
31
32
#include "acceptor.hxx"
33
#include <memory>
34
#include <mutex>
35
#include <string_view>
36
37
using namespace ::osl;
38
using namespace ::cppu;
39
using namespace ::com::sun::star::uno;
40
using namespace ::com::sun::star::lang;
41
using namespace ::com::sun::star::connection;
42
43
namespace {
44
45
    class OAcceptor : public WeakImplHelper< XAcceptor, XServiceInfo >
46
    {
47
    public:
48
        explicit OAcceptor(const Reference< XComponentContext > & xCtx);
49
        virtual ~OAcceptor() override;
50
    public:
51
        // Methods
52
        virtual Reference< XConnection > SAL_CALL accept( const OUString& sConnectionDescription ) override;
53
        virtual void SAL_CALL stopAccepting(  ) override;
54
55
    public: // XServiceInfo
56
                virtual OUString              SAL_CALL getImplementationName() override;
57
                virtual Sequence< OUString >  SAL_CALL getSupportedServiceNames() override;
58
                virtual sal_Bool              SAL_CALL supportsService(const OUString& ServiceName) override;
59
60
    private:
61
        std::unique_ptr<io_acceptor::PipeAcceptor> m_pPipe;
62
        std::unique_ptr<io_acceptor::SocketAcceptor> m_pSocket;
63
        std::mutex m_mutex;
64
        OUString m_sLastDescription;
65
        bool m_bInAccept;
66
67
        Reference< XMultiComponentFactory > _xSMgr;
68
        Reference< XComponentContext > _xCtx;
69
        Reference<XAcceptor>         _xAcceptor;
70
    };
71
72
}
73
74
OAcceptor::OAcceptor( const Reference< XComponentContext > & xCtx )
75
0
    : m_bInAccept( false )
76
0
    , _xSMgr( xCtx->getServiceManager() )
77
0
    , _xCtx( xCtx )
78
0
{}
79
80
OAcceptor::~OAcceptor()
81
0
{
82
0
    m_pPipe.reset();
83
0
}
84
85
namespace {
86
struct BeingInAccept
87
{
88
    /// @throws AlreadyAcceptingException
89
    BeingInAccept( bool *pFlag,std::u16string_view sConnectionDescription  )
90
0
        : m_pFlag( pFlag )
91
0
        {
92
0
              if( *m_pFlag )
93
0
                  throw AlreadyAcceptingException( OUString::Concat("AlreadyAcceptingException :") + sConnectionDescription );
94
0
              *m_pFlag = true;
95
0
        }
96
    ~BeingInAccept()
97
0
        {
98
0
            *m_pFlag = false;
99
0
        }
100
    bool *m_pFlag;
101
};
102
}
103
104
Reference< XConnection > OAcceptor::accept( const OUString &sConnectionDescription )
105
0
{
106
    // if there is a thread already accepting in this object, throw an exception.
107
0
    struct BeingInAccept guard( &m_bInAccept, sConnectionDescription );
108
109
0
    Reference< XConnection > r;
110
0
    if( !m_sLastDescription.isEmpty() &&
111
0
        m_sLastDescription != sConnectionDescription )
112
0
    {
113
        // instantiate another acceptor for different ports
114
0
        throw ConnectionSetupException( u"acceptor::accept called multiple times with different connection strings\n"_ustr );
115
0
    }
116
117
0
    if( m_sLastDescription.isEmpty() )
118
0
    {
119
        // setup the acceptor
120
0
        try
121
0
        {
122
0
            cppu::UnoUrlDescriptor aDesc(sConnectionDescription);
123
0
            if ( aDesc.getName() == "pipe" )
124
0
            {
125
0
                OUString aName(
126
0
                    aDesc.getParameter(
127
0
                        u"name"_ustr));
128
129
0
                m_pPipe.reset(new io_acceptor::PipeAcceptor(aName, sConnectionDescription));
130
131
0
                try
132
0
                {
133
0
                    m_pPipe->init();
134
0
                }
135
0
                catch( ... )
136
0
                {
137
0
                    {
138
0
                        std::unique_lock g( m_mutex );
139
0
                        m_pPipe.reset();
140
0
                    }
141
0
                    throw;
142
0
                }
143
0
            }
144
0
            else if ( aDesc.getName() == "socket" )
145
0
            {
146
0
                OUString aHost;
147
0
                if (aDesc.hasParameter(
148
0
                        u"host"_ustr))
149
0
                    aHost = aDesc.getParameter(
150
0
                        u"host"_ustr);
151
0
                else
152
0
                    aHost = "localhost";
153
0
                sal_uInt16 nPort = static_cast< sal_uInt16 >(
154
0
                    aDesc.getParameter(
155
0
                        u"port"_ustr).
156
0
                    toInt32());
157
0
                bool bTcpNoDelay
158
0
                    = aDesc.getParameter(
159
0
                        u"tcpnodelay"_ustr).toInt32() != 0;
160
161
0
                m_pSocket.reset(new io_acceptor::SocketAcceptor(
162
0
                    aHost, nPort, bTcpNoDelay, sConnectionDescription));
163
164
0
                try
165
0
                {
166
0
                    m_pSocket->init();
167
0
                }
168
0
                catch( ... )
169
0
                {
170
0
                    {
171
0
                        std::unique_lock g( m_mutex );
172
0
                        m_pSocket.reset();
173
0
                    }
174
0
                    throw;
175
0
                }
176
0
            }
177
0
            else
178
0
            {
179
0
                OUString delegatee = "com.sun.star.connection.Acceptor." + aDesc.getName();
180
0
                _xAcceptor.set(_xSMgr->createInstanceWithContext(delegatee, _xCtx), UNO_QUERY);
181
182
0
                if(!_xAcceptor.is())
183
0
                    throw ConnectionSetupException("Acceptor: unknown delegatee " + delegatee);
184
0
            }
185
0
        }
186
0
        catch (const rtl::MalformedUriException & rEx)
187
0
        {
188
0
            throw IllegalArgumentException(
189
0
                rEx.getMessage(),
190
0
                Reference< XInterface > (),
191
0
                0 );
192
0
        }
193
0
        m_sLastDescription = sConnectionDescription;
194
0
    }
195
196
0
    if( m_pPipe )
197
0
    {
198
0
        r = m_pPipe->accept();
199
0
    }
200
0
    else if( m_pSocket )
201
0
    {
202
0
        r = m_pSocket->accept();
203
0
    }
204
0
    else
205
0
    {
206
0
        r = _xAcceptor->accept(sConnectionDescription);
207
0
    }
208
209
0
    return r;
210
0
}
211
212
void SAL_CALL OAcceptor::stopAccepting(  )
213
0
{
214
0
    std::unique_lock guard( m_mutex );
215
216
0
    if( m_pPipe )
217
0
    {
218
0
        m_pPipe->stopAccepting();
219
0
    }
220
0
    else if ( m_pSocket )
221
0
    {
222
0
        m_pSocket->stopAccepting();
223
0
    }
224
0
    else if( _xAcceptor.is() )
225
0
    {
226
0
        _xAcceptor->stopAccepting();
227
0
    }
228
229
0
}
230
231
OUString OAcceptor::getImplementationName()
232
0
{
233
0
    return u"com.sun.star.comp.io.Acceptor"_ustr;
234
0
}
235
236
sal_Bool OAcceptor::supportsService(const OUString& ServiceName)
237
0
{
238
0
    return cppu::supportsService(this, ServiceName);
239
0
}
240
241
Sequence< OUString > OAcceptor::getSupportedServiceNames()
242
0
{
243
0
    return { u"com.sun.star.connection.Acceptor"_ustr };
244
0
}
245
246
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
247
io_OAcceptor_get_implementation(
248
    css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
249
0
{
250
0
    return cppu::acquire(new OAcceptor(context));
251
0
}
252
253
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */