Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qnetworkaccessdebugpipebackend.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5#include "QtCore/qdatastream.h"
6#include <QCoreApplication>
7#include <QStringList>
8#include <QUrlQuery>
9#include "private/qnoncontiguousbytedevice_p.h"
10
12
13using namespace Qt::StringLiterals;
14
15#ifdef QT_BUILD_INTERNAL
16
17enum {
18 ReadBufferSize = 16384,
19 WriteBufferSize = ReadBufferSize
20};
21
22QStringList QNetworkAccessDebugPipeBackendFactory::supportedSchemes() const
23{
24 return QStringList(QStringLiteral("debugpipe"));
25}
26
28QNetworkAccessDebugPipeBackendFactory::create(QNetworkAccessManager::Operation op,
29 const QNetworkRequest &request) const
30{
31 // is it an operation we know of?
32 switch (op) {
35 break;
36
37 default:
38 // no, we can't handle this operation
39 return nullptr;
40 }
41
42 QUrl url = request.url();
43 if (url.scheme() == "debugpipe"_L1)
44 return new QNetworkAccessDebugPipeBackend;
45 return nullptr;
46}
47
48QNetworkAccessDebugPipeBackend::QNetworkAccessDebugPipeBackend()
49 : QNetworkAccessBackend(QNetworkAccessBackend::TargetType::Networked),
50 bareProtocol(false),
51 hasUploadFinished(false),
52 hasDownloadFinished(false),
53 hasEverythingFinished(false),
54 bytesDownloaded(0),
55 bytesUploaded(0)
56{
57}
58
59QNetworkAccessDebugPipeBackend::~QNetworkAccessDebugPipeBackend()
60{
61 // this is signals disconnect, not network!
62 socket.disconnect(this); // we're not interested in the signals at this point
63}
64
65void QNetworkAccessDebugPipeBackend::open()
66{
67 socket.connectToHost(url().host(), url().port(12345));
68 socket.setReadBufferSize(ReadBufferSize);
69
70 // socket ready read -> we can push from socket to downstream
71 connect(&socket, SIGNAL(readyRead()), SLOT(socketReadyRead()));
73 connect(&socket, SIGNAL(disconnected()), SLOT(socketDisconnected()));
74 connect(&socket, SIGNAL(connected()), SLOT(socketConnected()));
75 // socket bytes written -> we can push more from upstream to socket
76 connect(&socket, SIGNAL(bytesWritten(qint64)), SLOT(socketBytesWritten(qint64)));
77
78 bareProtocol = QUrlQuery(url()).queryItemValue("bare"_L1) == "1"_L1;
79
80 if (operation() == QNetworkAccessManager::PutOperation) {
81 createUploadByteDevice();
82 QObject::connect(uploadByteDevice(), SIGNAL(readyRead()), this,
83 SLOT(uploadReadyReadSlot()));
84 QMetaObject::invokeMethod(this, "uploadReadyReadSlot", Qt::QueuedConnection);
85 }
86}
87
88void QNetworkAccessDebugPipeBackend::socketReadyRead()
89{
90 readyRead();
91}
92
93qint64 QNetworkAccessDebugPipeBackend::read(char *data, qint64 maxlen)
94{
95 qint64 haveRead = socket.read(data, maxlen);
96
97 if (haveRead == -1) {
98 hasDownloadFinished = true;
99 // this ensures a good last downloadProgress is emitted
100 auto h = headers();
102 setHeaders(std::move(h));
103 possiblyFinish();
104 return haveRead;
105 }
106
107 bytesDownloaded += haveRead;
108 return haveRead;
109}
110
111qint64 QNetworkAccessDebugPipeBackend::bytesAvailable() const
112{
113 return socket.bytesAvailable();
114}
115
116void QNetworkAccessDebugPipeBackend::socketBytesWritten(qint64)
117{
118 pushFromUpstreamToSocket();
119}
120
121void QNetworkAccessDebugPipeBackend::uploadReadyReadSlot()
122{
123 pushFromUpstreamToSocket();
124}
125
126void QNetworkAccessDebugPipeBackend::pushFromUpstreamToSocket()
127{
128 // FIXME
129 if (operation() == QNetworkAccessManager::PutOperation) {
130 if (hasUploadFinished)
131 return;
132
133 forever {
134 if (socket.bytesToWrite() >= WriteBufferSize)
135 return;
136
137 QByteArray data(WriteBufferSize, Qt::Uninitialized);
138 qint64 haveRead = uploadByteDevice()->peek(data.data(), data.size());
139 if (haveRead == -1) {
140 // EOF
141 hasUploadFinished = true;
142 possiblyFinish();
143 break;
144 } else if (haveRead == 0) {
145 // nothing to read right now, we will be called again later
146 break;
147 } else {
148 qint64 haveWritten;
149 data.truncate(haveRead);
150 haveWritten = socket.write(std::move(data));
151
152 if (haveWritten < 0) {
153 // write error!
154 QString msg = QCoreApplication::translate("QNetworkAccessDebugPipeBackend", "Write error writing to %1: %2")
155 .arg(url().toString(), socket.errorString());
157 finished();
158 return;
159 } else {
160 uploadByteDevice()->skip(haveWritten);
161 bytesUploaded += haveWritten;
162 }
163
164 //QCoreApplication::processEvents();
165 }
166 }
167 }
168}
169
170void QNetworkAccessDebugPipeBackend::possiblyFinish()
171{
172 if (hasEverythingFinished)
173 return;
174 hasEverythingFinished = true;
175
176 if ((operation() == QNetworkAccessManager::GetOperation) && hasDownloadFinished) {
177 socket.close();
178 finished();
179 } else if ((operation() == QNetworkAccessManager::PutOperation) && hasUploadFinished) {
180 socket.close();
181 finished();
182 }
183
184
185}
186
187void QNetworkAccessDebugPipeBackend::close()
188{
189 qWarning("QNetworkAccessDebugPipeBackend::closeDownstreamChannel() %d",operation());
190 //if (operation() == QNetworkAccessManager::GetOperation)
191 // socket.disconnectFromHost();
192}
193
194
195void QNetworkAccessDebugPipeBackend::socketError()
196{
197 qWarning("QNetworkAccessDebugPipeBackend::socketError() %d",socket.error());
199 switch (socket.error()) {
201 return; // socketDisconnected will be called
202
205 break;
206
207 default:
209 break;
210 }
211
212 error(code, QNetworkAccessDebugPipeBackend::tr("Socket error on %1: %2")
214 finished();
215 disconnect(&socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
216
217}
218
219void QNetworkAccessDebugPipeBackend::socketDisconnected()
220{
221 if (socket.bytesToWrite() == 0) {
222 // normal close
223 } else {
224 readyRead(); // @todo this is odd
225 // abnormal close
226 QString msg = QNetworkAccessDebugPipeBackend::tr("Remote host closed the connection prematurely on %1")
227 .arg(url().toString());
229 finished();
230 }
231}
232
233void QNetworkAccessDebugPipeBackend::socketConnected()
234{
235}
236
237
238#endif
239
241
242#include "moc_qnetworkaccessdebugpipebackend_p.cpp"
bool connected
virtual void setReadBufferSize(qint64 size)
Sets the size of QAbstractSocket's internal read buffer to be size bytes.
qint64 bytesToWrite() const override
Returns the number of bytes that are waiting to be written.
qint64 bytesAvailable() const override
Returns the number of incoming bytes that are waiting to be read.
void close() override
Closes the I/O device for the socket and calls disconnectFromHost() to close the socket's connection.
SocketError
This enum describes the socket errors that can occur.
virtual void connectToHost(const QString &hostName, quint16 port, OpenMode mode=ReadWrite, NetworkLayerProtocol protocol=AnyIPProtocol)
Attempts to make a connection to hostName on the given port.
SocketError error() const
Returns the type of error that last occurred.
\inmodule QtCore
Definition qbytearray.h:57
static QString translate(const char *context, const char *key, const char *disambiguation=nullptr, int n=-1)
\threadsafe
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
QString errorString() const
Returns a human-readable description of the last device error that occurred.
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read.
QNetworkAccessBackend is the base class for implementing support for schemes used by QNetworkAccessMa...
Operation
Indicates the operation this reply is processing.
NetworkError
Indicates all possible error conditions found during the processing of the request.
The QNetworkRequest class holds a request to be sent with QNetworkAccessManager.
QUrl url() const
Returns the URL this network request is referring to.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3236
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
Definition qstring.cpp:8870
\inmodule QtCore
Definition qurlquery.h:20
QString queryItemValue(const QString &key, QUrl::ComponentFormattingOptions encoding=QUrl::PrettyDecoded) const
Returns the query value associated with key key from the URL, using the options specified in encoding...
\inmodule QtCore
Definition qurl.h:94
QString scheme() const
Returns the scheme of the URL.
Definition qurl.cpp:1991
QAbstractSocket::SocketError socketError(QIODevice *device)
Combined button and popup list for selecting options.
@ QueuedConnection
constexpr Initialization Uninitialized
QList< QString > QStringList
Constructs a string list that contains the given string, str.
DBusConnection const char DBusError * error
EGLOutputPortEXT port
#define forever
Definition qforeach.h:78
#define qWarning
Definition qlogging.h:166
#define SLOT(a)
Definition qobjectdefs.h:52
#define SIGNAL(a)
Definition qobjectdefs.h:53
GLenum GLsizei GLuint GLint * bytesWritten
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLfloat GLfloat GLfloat GLfloat h
SSL_CTX int void * arg
#define QStringLiteral(str)
long long qint64
Definition qtypes.h:60
QUrl url("example.com")
[constructor-url-reference]
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection)
myObject disconnect()
[26]
QTcpSocket * socket
[1]
QNetworkRequest request(url)
char * toString(const MyType &t)
[31]
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...