Coverage Report

Created: 2025-07-07 10:01

/src/libreoffice/io/source/connector/ctr_socket.cxx
Line
Count
Source (jump to first uncovered line)
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
21
#include "connector.hxx"
22
#include <com/sun/star/io/IOException.hpp>
23
#include <utility>
24
25
using namespace ::osl;
26
using namespace ::com::sun::star::uno;
27
using namespace ::com::sun::star::io;
28
using namespace ::com::sun::star::connection;
29
30
31
namespace stoc_connector {
32
    template<class T>
33
    static void notifyListeners(SocketConnection * pCon, bool * notified, T t)
34
0
    {
35
0
        XStreamListener_hash_set listeners;
36
37
0
        {
38
0
            std::unique_lock guard(pCon->_mutex);
39
0
            if(!*notified)
40
0
            {
41
0
                *notified = true;
42
0
                listeners = pCon->_listeners;
43
0
            }
44
0
        }
45
46
0
        for(auto& listener : listeners)
47
0
            t(listener);
48
0
    }
Unexecuted instantiation: ctr_socket.cxx:void stoc_connector::notifyListeners<void (*)(com::sun::star::uno::Reference<com::sun::star::io::XStreamListener> const&)>(stoc_connector::SocketConnection*, bool*, void (*)(com::sun::star::uno::Reference<com::sun::star::io::XStreamListener> const&))
Unexecuted instantiation: ctr_socket.cxx:void stoc_connector::notifyListeners<stoc_connector::(anonymous namespace)::callError>(stoc_connector::SocketConnection*, bool*, stoc_connector::(anonymous namespace)::callError)
49
50
51
    static void callStarted(const Reference<XStreamListener>& xStreamListener)
52
0
    {
53
0
        xStreamListener->started();
54
0
    }
55
56
    namespace {
57
58
    struct callError {
59
        const Any & any;
60
61
        explicit callError(const Any & any);
62
63
        void operator () (const Reference<XStreamListener>& xStreamListener);
64
    };
65
66
    }
67
68
    callError::callError(const Any & aAny)
69
0
        : any(aAny)
70
0
    {
71
0
    }
72
73
    void callError::operator () (const Reference<XStreamListener>& xStreamListener)
74
0
    {
75
0
        xStreamListener->error(any);
76
0
    }
77
78
    static void callClosed(const Reference<XStreamListener>& xStreamListener)
79
0
    {
80
0
        xStreamListener->closed();
81
0
    }
82
83
84
    SocketConnection::SocketConnection( OUString sConnectionDescription ) :
85
0
        m_nStatus( 0 ),
86
0
        m_sDescription(std::move( sConnectionDescription )),
87
0
        _started(false),
88
0
        _closed(false),
89
0
        _error(false)
90
0
    {
91
        // make it unique
92
0
        m_sDescription += ",uniqueValue=";
93
0
        m_sDescription += OUString::number(
94
0
            sal::static_int_cast< sal_Int64 >(
95
0
                reinterpret_cast< sal_IntPtr >(&m_socket)) );
96
0
    }
97
98
    SocketConnection::~SocketConnection()
99
0
    {
100
0
    }
101
102
    void SocketConnection::completeConnectionString()
103
0
    {
104
0
        sal_Int32 nPort;
105
106
0
        nPort = m_socket.getPeerPort();
107
108
0
        m_sDescription +=
109
0
            ",peerPort=" + OUString::number( nPort ) +
110
0
            ",peerHost=" + m_socket.getPeerHost() +
111
0
            ",localPort=" + OUString::number( nPort ) +
112
0
            ",localHost=" + m_socket.getLocalHost( );
113
0
    }
114
115
    sal_Int32 SocketConnection::read( Sequence < sal_Int8 > & aReadBytes , sal_Int32 nBytesToRead )
116
0
    {
117
0
        if( ! m_nStatus )
118
0
        {
119
0
            notifyListeners(this, &_started, callStarted);
120
121
0
            if( aReadBytes.getLength() != nBytesToRead )
122
0
            {
123
0
                aReadBytes.realloc( nBytesToRead );
124
0
            }
125
0
            sal_Int32 i = m_socket.read( aReadBytes.getArray()  , aReadBytes.getLength() );
126
127
0
            if(i != nBytesToRead && m_socket.getError() != osl_Socket_E_None)
128
0
            {
129
0
                OUString message = "ctr_socket.cxx:SocketConnection::read: error - " +
130
0
                    m_socket.getErrorAsString();
131
132
0
                IOException ioException(message, static_cast<XConnection *>(this));
133
134
0
                Any any;
135
0
                any <<= ioException;
136
137
0
                notifyListeners(this, &_error, callError(any));
138
139
0
                throw ioException;
140
0
            }
141
142
0
            return i;
143
0
        }
144
0
        else
145
0
        {
146
0
            IOException ioException(u"ctr_socket.cxx:SocketConnection::read: error - connection already closed"_ustr, static_cast<XConnection *>(this));
147
148
0
            Any any;
149
0
            any <<= ioException;
150
151
0
            notifyListeners(this, &_error, callError(any));
152
153
0
            throw ioException;
154
0
        }
155
0
    }
156
157
    void SocketConnection::write( const Sequence < sal_Int8 > &seq )
158
0
    {
159
0
        if( ! m_nStatus )
160
0
        {
161
0
            if( m_socket.write( seq.getConstArray() , seq.getLength() ) != seq.getLength() )
162
0
            {
163
0
                OUString message = "ctr_socket.cxx:SocketConnection::write: error - " +
164
0
                    m_socket.getErrorAsString();
165
166
0
                IOException ioException(message, static_cast<XConnection *>(this));
167
168
0
                Any any;
169
0
                any <<= ioException;
170
171
0
                notifyListeners(this, &_error, callError(any));
172
173
0
                throw ioException;
174
0
            }
175
0
        }
176
0
        else
177
0
        {
178
0
            IOException ioException(u"ctr_socket.cxx:SocketConnection::write: error - connection already closed"_ustr, static_cast<XConnection *>(this));
179
180
0
            Any any;
181
0
            any <<= ioException;
182
183
0
            notifyListeners(this, &_error, callError(any));
184
185
0
            throw ioException;
186
0
        }
187
0
    }
188
189
    void SocketConnection::flush( )
190
0
    {
191
192
0
    }
193
194
    void SocketConnection::close()
195
0
    {
196
            // ensure that close is called only once
197
0
        if( 1 == osl_atomic_increment( (&m_nStatus) ) )
198
0
        {
199
0
            m_socket.shutdown();
200
0
            notifyListeners(this, &_closed, callClosed);
201
0
        }
202
0
    }
203
204
    OUString SocketConnection::getDescription()
205
0
    {
206
0
        return m_sDescription;
207
0
    }
208
209
210
    // XConnectionBroadcaster
211
    void SAL_CALL SocketConnection::addStreamListener(const Reference<XStreamListener> & aListener)
212
0
    {
213
0
        std::unique_lock guard(_mutex);
214
215
0
        _listeners.insert(aListener);
216
0
    }
217
218
    void SAL_CALL SocketConnection::removeStreamListener(const Reference<XStreamListener> & aListener)
219
0
    {
220
0
        std::unique_lock guard(_mutex);
221
222
0
        _listeners.erase(aListener);
223
0
    }
224
}
225
226
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */