qint64 VirtualSerialDevice::writeData(const char *data, qint64 maxSize)
{
    QMutexLocker locker(&lock);
    qint64 bytesWritten;
    bool needToWait = tryFlushPendingBuffers(locker, EmitBytesWrittenAsync);
    if (!needToWait) {
        needToWait = tryWrite(data, maxSize, bytesWritten);
        if (needToWait && bytesWritten > 0) {
            // Wrote some of the buffer, adjust pointers to point to the remainder that needs queueing
            data += bytesWritten;
            maxSize -= bytesWritten;
        }
    }

    if (needToWait) {
        pendingWrites.append(QByteArray(data, maxSize));
        d->writeUnblockedNotifier->setEnabled(true);
        // Now wait for the writeUnblocked signal or for a call to waitForBytesWritten
        return bytesWritten + maxSize;
    } else {
        //emitBytesWrittenIfNeeded(locker, bytesWritten);
        // Can't emit bytesWritten directly from writeData - means clients end up recursing
        emit AsyncCall_emitBytesWrittenIfNeeded(bytesWritten);
        return bytesWritten;
    }
}
/* Returns true if EAGAIN encountered. Emits (or queues) bytesWritten for any buffers written.
 * If stopAfterWritingOneBuffer is true, return immediately if a single buffer is written, rather than
 * attempting to drain the whole queue.
 * Doesn't modify notifier.
 */
bool VirtualSerialDevice::tryFlushPendingBuffers(QMutexLocker& locker, FlushPendingOptions flags)
{
    while (pendingWrites.count() > 0) {
        // Try writing everything we've got, until we hit EAGAIN
        const QByteArray& data = pendingWrites[0];
        qint64 bytesWritten;
        bool needToWait = tryWrite(data.constData(), data.size(), bytesWritten);
        if (needToWait) {
            if (bytesWritten > 0) {
                // We wrote some of the data, update the pending queue
                QByteArray remainder = data.mid(bytesWritten);
                pendingWrites.removeFirst();
                pendingWrites.insert(0, remainder);
            }
            return needToWait;
        } else {
            pendingWrites.removeFirst();
            if (flags & EmitBytesWrittenAsync) {
                emit AsyncCall_emitBytesWrittenIfNeeded(bytesWritten);
            } else {
                emitBytesWrittenIfNeeded(locker, bytesWritten);
            }
            if (flags & StopAfterWritingOneBuffer) return false;
            // Otherwise go round loop again
        }
    }
    return false; // no EAGAIN encountered
}
Ejemplo n.º 3
0
	QByteArray readBody(int size)
	{
		if(server)
		{
			QByteArray out = requestBodyBuf.take(size);
			if(out.isEmpty())
				return out;

			pendingInCredits += out.size();

			if(!pausing && !paused)
			{
				ZhttpResponsePacket p;
				p.type = ZhttpResponsePacket::Credit;
				p.credits = pendingInCredits;
				pendingInCredits = 0;
				writePacket(p);
			}

			return out;
		}
		else
		{
			QByteArray out = responseBodyBuf.take(size);
			if(out.isEmpty())
				return out;

			pendingInCredits += out.size();

			if(state == ClientReceiving)
				tryWrite(); // this should not emit signals in current state

			return out;
		}
	}
Ejemplo n.º 4
0
void Connection::sendMsg(SendPacket* p)
{
	if (m_status != CONN_STATUS_CONNECTED)
	{
		LOGERROR() << "sendmsg status not connected"
			<<"id"<<m_id
			<<LOGEND();
		return;
	}
	short opCode = p->getOPCode();
	std::string body = p->getData();

	unsigned int pack = (13 << 24) + (body.size() & 0xFFFFFF);

	char header[MSG_HEADER_SIZE] = {0};
	memmove(header,					(char*)&opCode, sizeof(opCode));
	memmove(header+sizeof(opCode),	(char*)&pack,	sizeof(pack));

	std::stringstream ss;
	ss << std::string(header, 6) << body;
	m_outData.push_back(ss.str());
	LOGNET() << "try send msg " << opCode << " pack size " << body.size() << LOGEND();

	tryWrite();
}
Ejemplo n.º 5
0
void Connection::handleWrite(const boost::system::error_code& error, size_t len)
{
	if(!error)
	{
		m_writeStatus = SW_STATUS_WRITEDONE;

		assert(m_outData.size() > 0);
		// ok write some chars
		//std::string& buf = m_outData.front();
		// first buffer all flushed
		if (len == m_tempBuf.length())
		{
			LOGNET() << "<<< write full " << len << " " 
				<<"id"<<m_id
				<< LOGEND();
			m_outData.pop_front();
			tryWrite();
		}
		else
		{
			//LOGNET() << "<<< write partial " << len << " should " << buf.length() << " " 
			LOGNET() << "<<< write partial " << len << " should " << m_tempBuf.length() << " " 
				<<"id"<<m_id
				<< LOGEND();
			assert(len < m_tempBuf.length());
			//buf = buf.substr(len);
			m_tempBuf = m_tempBuf.substr(len);
			tryWrite();
		}
	}
	else
	{
		if (m_status == CONN_STATUS_CONNECTED)
		{
			m_status = CONN_STATUS_DISCONNECT;
		}
		else
		{
			// triggered by other event
		}

		if (m_errHandler)
		{
			m_errHandler(error, this, "handlewrite");
		}
	}
}
	void CBAWMeshWriter::exportAsBlob<asset::ICPUBuffer>(asset::ICPUBuffer* _obj, uint32_t _headerIdx, io::IWriteFile* _file, SContext& _ctx)
	{
        const asset::E_WRITER_FLAGS flags = _ctx.writerOverride->getAssetWritingFlags(_ctx.inner, _obj, 3u);
        const uint8_t* encrPwd = nullptr;
        _ctx.writerOverride->getEncryptionKey(encrPwd, _ctx.inner, _obj, 3u);
        const float comprLvl = _ctx.writerOverride->getAssetCompressionLevel(_ctx.inner, _obj, 3u);
		tryWrite(_obj->getPointer(), _file, _ctx, _obj->getSize(), _headerIdx, flags, encrPwd, comprLvl);
	}
Ejemplo n.º 7
0
void
RemotePluginClient::sendMIDIData(unsigned char *data, int *frameoffsets, int events)
{
    writeOpcode(&m_shmControl->ringBuffer, RemotePluginSendMIDIData);
    writeInt(&m_shmControl->ringBuffer, events);
    tryWrite(&m_shmControl->ringBuffer, data, events * 3);

    if (!frameoffsets) {
	// This should not happen with a good client, but we'd better
	// cope as well as possible with the lazy ol' degenerates
	frameoffsets = (int *)alloca(events * sizeof(int));
	memset(frameoffsets, 0, events * sizeof(int));
    }

//    std::cerr << "RemotePluginClient::sendMIDIData(" << events << ")" << std::endl;

    tryWrite(&m_shmControl->ringBuffer, frameoffsets, events * sizeof(int));
    commitWrite(&m_shmControl->ringBuffer);
}
Ejemplo n.º 8
0
//!
//! Writes array \a a to the stream.
void ByteStream::write(const QByteArray &a)
{
	if(!isOpen())
		return;

	bool doWrite = bytesToWrite() == 0 ? true: false;
	appendWrite(a);
	if(doWrite)
		tryWrite();
}
	void CBAWMeshWriter::exportAsBlob<scene::CFinalBoneHierarchy>(scene::CFinalBoneHierarchy* _obj, uint32_t _headerIdx, io::IWriteFile* _file, SContext& _ctx)
	{
		uint8_t stackData[1u<<14]; // 16kB
        asset::FinalBoneHierarchyBlobV1* data = asset::FinalBoneHierarchyBlobV1::createAndTryOnStack(_obj,stackData,sizeof(stackData));

		tryWrite(data, _file, _ctx, asset::FinalBoneHierarchyBlobV1::calcBlobSizeForObj(_obj), _headerIdx, asset::EWF_NONE);

		if ((uint8_t*)data != stackData)
			_IRR_ALIGNED_FREE(data);
	}
Ejemplo n.º 10
0
void BConsole::sn_write()
{
	d->w->deleteLater();
	d->w = 0;

	if(bytesToWrite() > 0)
		tryWrite();
	if(bytesToWrite() == 0 && d->closing) {
		d->closing = false;
		d->closed = true;
		delayedCloseFinished();
	}
}
	void CBAWMeshWriter::exportAsBlob<asset::ICPUSkinnedMesh>(asset::ICPUSkinnedMesh* _obj, uint32_t _headerIdx, io::IWriteFile* _file, SContext& _ctx)
	{
		uint8_t stackData[1u << 14];
        asset::SkinnedMeshBlobV1* data = asset::SkinnedMeshBlobV1::createAndTryOnStack(_obj,stackData,sizeof(stackData));

        const asset::E_WRITER_FLAGS flags = _ctx.writerOverride->getAssetWritingFlags(_ctx.inner, _obj, 0u);
        const uint8_t* encrPwd = nullptr;
        _ctx.writerOverride->getEncryptionKey(encrPwd, _ctx.inner, _obj, 0u);
        const float comprLvl = _ctx.writerOverride->getAssetCompressionLevel(_ctx.inner, _obj, 0u);
		tryWrite(data, _file, _ctx, asset::SkinnedMeshBlobV1::calcBlobSizeForObj(_obj), _headerIdx, flags, encrPwd, comprLvl);

		if ((uint8_t*)data != stackData)
			_IRR_ALIGNED_FREE(data);
	}
	void CBAWMeshWriter::exportAsBlob<asset::ICPUTexture>(asset::ICPUTexture* _obj, uint32_t _headerIdx, io::IWriteFile* _file, SContext& _ctx)
	{
        asset::ICPUTexture* tex = _obj;

        const WriteProperties* props = reinterpret_cast<const WriteProperties*>(_ctx.inner.params.userData);
		const io::path fileDir = props->relPath.size() ? props->relPath : io::IFileSystem::getFileDir(m_fileSystem->getAbsolutePath(_file->getFileName())); // get relative-file's directory
		io::path path = m_fileSystem->getRelativeFilename(tex->getCacheKey().c_str(), fileDir); // get texture-file path relative to the file's directory
		const uint32_t len = strlen(path.c_str()) + 1;

        const asset::E_WRITER_FLAGS flags = _ctx.writerOverride->getAssetWritingFlags(_ctx.inner, _obj, 2u);
        const uint8_t* encrPwd = nullptr;
        _ctx.writerOverride->getEncryptionKey(encrPwd, _ctx.inner, _obj, 2u);
        const float comprLvl = _ctx.writerOverride->getAssetCompressionLevel(_ctx.inner, _obj, 2u);
		tryWrite(&path[0], _file, _ctx, len, _headerIdx, flags, encrPwd, comprLvl);
	}
Ejemplo n.º 13
0
	QByteArray readResponseBody(int size)
	{
		if(size != -1)
			size = qMin(size, in.size());
		else
			size = in.size();

		if(size == 0)
			return QByteArray();

		QByteArray out = in.mid(0, size);
		in = in.mid(size);

		pendingInCredits += size;

		if(state == Receiving)
			tryWrite(); // this should not emit signals in current state

		return out;
	}
Ejemplo n.º 14
0
	void handle(const ZhttpResponsePacket &packet)
	{
		if(state == ClientRequestStartWait)
		{
			if(packet.from.isEmpty())
			{
				state = Stopped;
				errored = true;
				errorCondition = ErrorGeneric;
				cleanup();
				log_warning("zhttp client: error id=%s initial ack for streamed input request did not contain from field", packet.id.data());
				emit q->error();
				return;
			}

			toAddress = packet.from;

			state = ClientRequesting;

			startKeepAlive();
		}
		else if(state == ClientRequestFinishWait)
		{
			toAddress = packet.from;

			state = ClientReceiving;

			if(!doReq)
				startKeepAlive();
		}

		if(packet.type == ZhttpResponsePacket::Error)
		{
			errored = true;
			errorCondition = convertError(packet.condition);

			log_debug("zhttp client: error id=%s cond=%s", packet.id.data(), packet.condition.data());

			state = Stopped;
			cleanup();
			emit q->error();
			return;
		}
		else if(packet.type == ZhttpResponsePacket::Cancel)
		{
			log_debug("zhttp client: received cancel id=%s", packet.id.data());

			errored = true;
			errorCondition = ErrorGeneric;
			state = Stopped;
			cleanup();
			emit q->error();
			return;
		}

		// if non-req mode, check sequencing
		if(!doReq && packet.seq != inSeq)
		{
			log_warning("zhttp client: error id=%s received message out of sequence, canceling", packet.id.data());

			// if this was not an error packet, send cancel
			if(packet.type != ZhttpResponsePacket::Error && packet.type != ZhttpResponsePacket::Cancel)
			{
				ZhttpRequestPacket p;
				p.type = ZhttpRequestPacket::Cancel;
				writePacket(p);
			}

			state = Stopped;
			errored = true;
			errorCondition = ErrorGeneric;
			cleanup();
			emit q->error();
			return;
		}

		++inSeq;

		refreshTimeout();

		if(doReq && (packet.type != ZhttpResponsePacket::Data || packet.more))
		{
			log_warning("zhttp/zws client req: received invalid req response");

			state = Stopped;
			errored = true;
			errorCondition = ErrorGeneric;
			cleanup();
			emit q->error();
			return;
		}

		if(packet.type == ZhttpResponsePacket::Data)
		{
			if(!haveResponseValues)
			{
				haveResponseValues = true;

				responseCode = packet.code;
				responseReason = packet.reason;
				responseHeaders = packet.headers;
			}

			if(doReq)
			{
				if(responseBodyBuf.size() + packet.body.size() > REQ_BUF_MAX)
					log_warning("zhttp client req: id=%s server response too large", packet.id.data());
			}
			else
			{
				if(responseBodyBuf.size() + packet.body.size() > IDEAL_CREDITS)
					log_warning("zhttp client: id=%s server is sending too fast", packet.id.data());
			}

			responseBodyBuf += packet.body;

			if(!doReq && packet.credits > 0)
			{
				outCredits += packet.credits;
				if(outCredits > 0)
				{
					// try to write anything that was waiting on credits
					QPointer<QObject> self = this;
					tryWrite();
					if(!self)
						return;
				}
			}

			if(packet.more)
			{
				if(!packet.body.isEmpty())
					emit q->readyRead();
			}
			else
			{
				// always emit readyRead here even if body is empty, for EOF
				state = Stopped;
				cleanup();
				emit q->readyRead();
			}
		}
		else if(packet.type == ZhttpResponsePacket::Credit)
		{
			if(packet.credits > 0)
			{
				outCredits += packet.credits;
				if(outCredits > 0)
					tryWrite();
			}
		}
		else if(packet.type == ZhttpResponsePacket::KeepAlive)
		{
			// nothing to do
		}
		else
		{
			log_debug("zhttp client: unsupported packet type id=%s type=%d", packet.id.data(), (int)packet.type);
		}
	}
Ejemplo n.º 15
0
	void handle(const ZhttpRequestPacket &packet)
	{
		if(paused)
			return;

		if(packet.type == ZhttpRequestPacket::Error)
		{
			errored = true;
			errorCondition = convertError(packet.condition);

			log_debug("zhttp server: error id=%s cond=%s", packet.id.data(), packet.condition.data());

			state = Stopped;
			cleanup();
			emit q->error();
			return;
		}
		else if(packet.type == ZhttpRequestPacket::Cancel)
		{
			log_debug("zhttp server: received cancel id=%s", packet.id.data());

			errored = true;
			errorCondition = ErrorGeneric;
			state = Stopped;
			cleanup();
			emit q->error();
			return;
		}

		if(packet.seq != inSeq)
		{
			log_warning("zhttp server: error id=%s received message out of sequence, canceling", packet.id.data());

			// if this was not an error packet, send cancel
			if(packet.type != ZhttpRequestPacket::Error && packet.type != ZhttpRequestPacket::Cancel)
			{
				ZhttpResponsePacket p;
				p.type = ZhttpResponsePacket::Cancel;
				writePacket(p);
			}

			state = Stopped;
			errored = true;
			errorCondition = ErrorGeneric;
			cleanup();
			emit q->error();
			return;
		}

		++inSeq;

		refreshTimeout();

		if(packet.type == ZhttpRequestPacket::Data)
		{
			requestBodyBuf += packet.body;

			bool done = haveRequestBody;

			if(!packet.more)
			{
				haveRequestBody = true;
				state = ServerResponseWait;
			}

			if(packet.credits > 0)
				outCredits += packet.credits;

			if(!packet.body.isEmpty() || (!done && haveRequestBody))
				emit q->readyRead();
		}
		else if(packet.type == ZhttpRequestPacket::Credit)
		{
			if(packet.credits > 0)
			{
				outCredits += packet.credits;
				tryWrite();
			}
		}
		else if(packet.type == ZhttpRequestPacket::KeepAlive)
		{
			// nothing to do
		}
		else if(packet.type == ZhttpRequestPacket::HandoffProceed)
		{
			if(pausing)
			{
				pausing = false;
				paused = true;
				emit q->paused();
			}
		}
		else
		{
			log_debug("zhttp server: unsupported packet type id=%s type=%d", packet.id.data(), (int)packet.type);
		}
	}
Ejemplo n.º 16
0
	void handle(const ZhttpResponsePacket &packet)
	{
		if(packet.type == ZhttpResponsePacket::Error)
		{
			errorCondition = convertError(packet.condition);

			log_debug("zws client: error id=%s cond=%s", packet.id.data(), packet.condition.data());

			responseCode = packet.code;
			responseReason = packet.reason;
			responseHeaders = packet.headers;
			responseBody = packet.body;

			state = Idle;
			cleanup();
			emit q->error();
			return;
		}
		else if(packet.type == ZhttpResponsePacket::Cancel)
		{
			log_debug("zws client: received cancel id=%s", packet.id.data());

			errorCondition = ErrorGeneric;
			state = Idle;
			cleanup();
			emit q->error();
			return;
		}

		if(!packet.from.isEmpty())
			toAddress = packet.from;

		if(packet.seq != inSeq)
		{
			log_warning("zws client: error id=%s received message out of sequence, canceling", packet.id.data());

			tryRespondCancel(packet);

			state = Idle;
			errorCondition = ErrorGeneric;
			cleanup();
			emit q->error();
			return;
		}

		if(!toAddress.isEmpty() && !keepAliveTimer->isActive())
			startKeepAlive();

		++inSeq;

		refreshTimeout();

		if(state == Connecting)
		{
			if(packet.type != ZhttpResponsePacket::Data && packet.type != ZhttpResponsePacket::Credit && packet.type != ZhttpResponsePacket::KeepAlive)
			{
				state = Idle;
				errorCondition = ErrorGeneric;
				cleanup();
				log_warning("zws client: error id=%s initial response wrong type", packet.id.data());
				emit q->error();
				return;
			}

			if(packet.from.isEmpty())
			{
				state = Idle;
				errorCondition = ErrorGeneric;
				cleanup();
				log_warning("zws client: error id=%s initial ack did not contain from field", packet.id.data());
				emit q->error();
				return;
			}
		}

		if(packet.type == ZhttpResponsePacket::Data || packet.type == ZhttpResponsePacket::Ping || packet.type == ZhttpResponsePacket::Pong)
		{
			if(state == Connecting)
			{
				// this is assured earlier
				assert(packet.type == ZhttpResponsePacket::Data);

				responseCode = packet.code;
				responseReason = packet.reason;
				responseHeaders = packet.headers;

				if(packet.credits > 0)
					outCredits += packet.credits;

				state = Connected;
				update();
				emit q->connected();
			}
			else
			{
				if(inSize + packet.body.size() > IDEAL_CREDITS)
					log_warning("zws client: id=%s server is sending too fast", packet.id.data());

				if(packet.type == ZhttpResponsePacket::Data)
				{
					handleIncomingDataPacket(packet.contentType, packet.body, packet.more);
				}
				else if(packet.type == ZhttpResponsePacket::Ping)
				{
					inFrames += Frame(Frame::Ping, packet.body, false);
					inSize += packet.body.size();
				}
				else if(packet.type == ZhttpResponsePacket::Pong)
				{
					inFrames += Frame(Frame::Pong, packet.body, false);
					inSize += packet.body.size();
				}

				if(packet.credits > 0)
				{
					outCredits += packet.credits;
					if(outCredits > 0)
					{
						// try to write anything that was waiting on credits
						QPointer<QObject> self = this;
						tryWrite();
						if(!self)
							return;
					}
				}

				emit q->readyRead();
			}
		}
		else if(packet.type == ZhttpResponsePacket::Close)
		{
			handlePeerClose(packet.code);
		}
		else if(packet.type == ZhttpResponsePacket::Credit)
		{
			if(packet.credits > 0)
			{
				outCredits += packet.credits;
				if(outCredits > 0)
					tryWrite();
			}
		}
		else if(packet.type == ZhttpResponsePacket::KeepAlive)
		{
			// nothing to do
		}
		else
		{
			log_debug("zws client: unsupported packet type id=%s type=%d", packet.id.data(), (int)packet.type);
		}
	}
Ejemplo n.º 17
0
	void handleRequest(ZhttpRequest *_req, const QByteArray &jsonpCallback, const QByteArray &lastPart, const QByteArray &body)
	{
		connect(_req, SIGNAL(bytesWritten(int)), SLOT(req_bytesWritten(int)));
		connect(_req, SIGNAL(error()), SLOT(req_error()));

		if(lastPart == "xhr" || lastPart == "jsonp")
		{
			if(req)
			{
				QVariantList out;
				out += 2010;
				out += QString("Another connection still open");

				requests.insert(_req, new RequestItem(_req, jsonpCallback, RequestItem::Background, true));
				respondOk(_req, out, "c", jsonpCallback);
				return;
			}

			if(peerClosed)
			{
				QVariantList out;
				out += 3000;
				out += QString("Client already closed connection");

				requests.insert(_req, new RequestItem(_req, jsonpCallback, RequestItem::Background, true));
				respondOk(_req, out, "c", jsonpCallback);
				return;
			}

			req = _req;
			requests.insert(req, new RequestItem(req, jsonpCallback, RequestItem::Receive));
			keepAliveTimer->start(KEEPALIVE_TIMEOUT * 1000);

			tryWrite();
		}
		else if(lastPart == "xhr_send" || lastPart == "jsonp_send")
		{
			// only allow one outstanding send request at a time
			if(findFirstSendRequest())
			{
				requests.insert(_req, new RequestItem(_req, jsonpCallback, RequestItem::Background, true));
				respondError(_req, 400, "Bad Request", "Already sending");
				return;
			}

			QByteArray param;

			if(_req->requestMethod() == "POST")
			{
				if(lastPart == "xhr_send")
				{
					// assume json
					param = body;
				}
				else // jsonp_send
				{
					// assume form encoded
					foreach(const QByteArray &kv, body.split('&'))
					{
						int at = kv.indexOf('=');
						if(at == -1)
							continue;
						if(QUrl::fromPercentEncoding(kv.mid(0, at)) == "d")
						{
							param = QUrl::fromPercentEncoding(kv.mid(at + 1)).toUtf8();
							break;
						}
					}
				}
			}
			else // GET
			{
				QUrlQuery query(_req->requestUri());
				param = query.queryItemValue("d").toUtf8();
			}

			QJsonParseError error;
			QJsonDocument doc = QJsonDocument::fromJson(param, &error);
			if(error.error != QJsonParseError::NoError || !doc.isArray())
			{
				requests.insert(_req, new RequestItem(_req, jsonpCallback, RequestItem::Background, true));
				respondError(_req, 400, "Bad Request", "Payload expected");
				return;
			}

			QVariantList messages = doc.array().toVariantList();

			QList<Frame> frames;
			int bytes = 0;
			foreach(const QVariant &vmessage, messages)
			{
				if(vmessage.type() != QVariant::String)
				{
					requests.insert(_req, new RequestItem(_req, jsonpCallback, RequestItem::Background, true));
					respondError(_req, 400, "Bad Request", "Payload expected");
					return;
				}

				QByteArray data = vmessage.toString().toUtf8();
				if(data.size() > BUFFER_SIZE)
				{
					requests.insert(_req, new RequestItem(_req, jsonpCallback, RequestItem::Background, true));
					respondError(_req, 400, "Bad Request", "Message too large");
					return;
				}

				frames += Frame(Frame::Text, data, false);
				bytes += data.size();
			}

			if(frames.isEmpty())
			{
				requests.insert(_req, new RequestItem(_req, jsonpCallback, RequestItem::Background, true));
				respondOk(_req, QString("ok"), jsonpCallback);
				return;
			}

			RequestItem *ri = new RequestItem(_req, jsonpCallback, RequestItem::Send);
			requests.insert(_req, ri);
			ri->sendFrames = frames;
			ri->sendBytes = bytes;

			tryRead();
		}
Ejemplo n.º 18
0
	void handle(const ZurlResponsePacket &packet)
	{
		if(state == RequestStartWait)
		{
			if(packet.replyAddress.isEmpty())
			{
				state = Private::Stopped;
				errorCondition = ErrorGeneric;
				cleanup();
				log_warning("initial ack for streamed input request did not contain reply-address");
				emit q->error();
				return;
			}

			replyAddress = packet.replyAddress;

			state = Requesting;
		}
		else if(state == RequestFinishWait)
		{
			replyAddress = packet.replyAddress;

			state = Receiving;
		}

		if(packet.isError)
		{
			// zurl conditions:
			//  remote-connection-failed
			//  connection-timeout
			//  tls-error
			//  bad-request
			//  policy-violation
			//  max-size-exceeded
			//  cancel

			QByteArray cond = packet.condition;
			if(cond == "policy-violation")
				errorCondition = ErrorPolicy;
			else if(cond == "remote-connection-failed")
				errorCondition = ErrorConnect;
			else if(cond == "tls-error")
				errorCondition = ErrorTls;
			else if(cond == "length-required")
				errorCondition = ErrorLengthRequired;
			else if(cond == "connection-timeout")
				errorCondition = ErrorTimeout;
			else // bad-request, max-size-exceeded, cancel
				errorCondition = ErrorGeneric;

			state = Private::Stopped;
			cleanup();
			emit q->error();
			return;
		}

		if(packet.seq != inSeq)
		{
			log_warning("received message out of sequence, canceling");

			// if this was not an error packet, send cancel
			if(packet.condition.isEmpty())
			{
				ZurlRequestPacket p;
				p.id = rid.second;
				p.seq = outSeq++;
				p.cancel = true;
				manager->write(p, replyAddress);
			}

			state = Private::Stopped;
			errorCondition = ErrorGeneric;
			cleanup();
			emit q->error();
			return;
		}

		++inSeq;

		refreshTimeout();

		bool doReadyRead = false;

		if(!packet.body.isNull())
		{
			if(!haveResponseValues)
			{
				haveResponseValues = true;

				responseCode = packet.code;
				responseStatus = packet.reason;
				responseHeaders = packet.headers;
			}

			if(in.size() + packet.body.size() > IDEAL_CREDITS)
				log_warning("zurl is sending too fast");

			in += packet.body;

			if(packet.more)
			{
				if(!packet.body.isEmpty())
					doReadyRead = true;
			}
			else
			{
				// always emit readyRead here even if body is empty, for EOF
				state = Private::Stopped;
				cleanup();
				emit q->readyRead();
				return;
			}
		}

		if(packet.credits > 0)
			outCredits += packet.credits;

		// the only reason we should need to write as a result of a read
		//   is if we were given credits or we have credits to give
		if(packet.credits > 0 || pendingInCredits > 0)
		{
			QPointer<QObject> self = this;
			tryWrite();
			if(!self)
				return;
		}

		if(doReadyRead)
			emit q->readyRead();
	}
Ejemplo n.º 19
0
void
RemotePluginClient::setDebugLevel(RemotePluginDebugLevel level)
{
    writeOpcode(m_controlRequestFd, RemotePluginSetDebugLevel);
    tryWrite(m_controlRequestFd, &level, sizeof(RemotePluginDebugLevel));
}
Ejemplo n.º 20
0
RemotePluginServer::RemotePluginServer(std::string fileIdentifiers) :
    m_bufferSize(-1),
    m_numInputs(-1),
    m_numOutputs(-1),
    m_controlRequestFd(-1),
    m_controlResponseFd(-1),
    m_shmFd(-1),
    m_shmControlFd(-1),
    m_controlRequestFileName(0),
    m_controlResponseFileName(0),
    m_shmFileName(0),
    m_shmControlFileName(0),
    m_shm(0),
    m_shmSize(0),
    m_shmControl(0),
    m_inputs(0),
    m_outputs(0)
{
    char tmpFileBase[60];
    
    sprintf(tmpFileBase, "/tmp/rplugin_crq_%s",
	    fileIdentifiers.substr(0, 6).c_str());
    m_controlRequestFileName = strdup(tmpFileBase);

    if ((m_controlRequestFd = open(m_controlRequestFileName, O_RDONLY)) < 0) {
	cleanup();
	throw((std::string)"Failed to open FIFO");
    }
    
    sprintf(tmpFileBase, "/tmp/rplugin_crs_%s",
	    fileIdentifiers.substr(6, 6).c_str());
    m_controlResponseFileName = strdup(tmpFileBase);

    if ((m_controlResponseFd = open(m_controlResponseFileName, O_WRONLY)) < 0) {
	cleanup();
	throw((std::string)"Failed to open FIFO");
    }

    bool b = false;

    sprintf(tmpFileBase, "/dssi-vst-rplugin_shc_%s",
	    fileIdentifiers.substr(12, 6).c_str());
    m_shmControlFileName = strdup(tmpFileBase);

    m_shmControlFd = shm_open(m_shmControlFileName, O_RDWR, 0);
    if (m_shmControlFd < 0) {
        tryWrite(m_controlResponseFd, &b, sizeof(bool));
	cleanup();
	throw((std::string)"Failed to open or create shared memory file");
    }

    m_shmControl = static_cast<ShmControl *>(mmap(0, sizeof(ShmControl), PROT_READ | PROT_WRITE, MAP_SHARED, m_shmControlFd, 0));
    if (!m_shmControl) {
        tryWrite(m_controlResponseFd, &b, sizeof(bool));
        cleanup();
        throw((std::string)"Failed to mmap shared memory file");
    }

    sprintf(tmpFileBase, "/dssi-vst-rplugin_shm_%s",
	    fileIdentifiers.substr(18, 6).c_str());
    m_shmFileName = strdup(tmpFileBase);

    if ((m_shmFd = shm_open(m_shmFileName, O_RDWR, 0)) < 0) {
	tryWrite(m_controlResponseFd, &b, sizeof(bool));
	cleanup();
	throw((std::string)"Failed to open shared memory file");
    }

    b = true;
    tryWrite(m_controlResponseFd, &b, sizeof(bool));
}
Ejemplo n.º 21
0
	void handle(const ZhttpRequestPacket &packet)
	{
		if(packet.type == ZhttpRequestPacket::Error)
		{
			errorCondition = convertError(packet.condition);

			log_debug("zws server: error id=%s cond=%s", packet.id.data(), packet.condition.data());

			state = Idle;
			cleanup();
			emit q->error();
			return;
		}
		else if(packet.type == ZhttpRequestPacket::Cancel)
		{
			log_debug("zws server: received cancel id=%s", packet.id.data());

			errorCondition = ErrorGeneric;
			state = Idle;
			cleanup();
			emit q->error();
			return;
		}

		if(packet.seq != inSeq)
		{
			log_warning("zws server: error id=%s received message out of sequence, canceling", packet.id.data());

			tryRespondCancel(packet);

			state = Idle;
			errorCondition = ErrorGeneric;
			cleanup();
			emit q->error();
			return;
		}

		++inSeq;

		refreshTimeout();

		if(packet.type == ZhttpRequestPacket::Data || packet.type == ZhttpRequestPacket::Ping || packet.type == ZhttpRequestPacket::Pong)
		{
			if(inSize + packet.body.size() > IDEAL_CREDITS)
				log_warning("zws client: id=%s server is sending too fast", packet.id.data());

			if(packet.type == ZhttpRequestPacket::Data)
			{
				handleIncomingDataPacket(packet.contentType, packet.body, packet.more);
			}
			else if(packet.type == ZhttpRequestPacket::Ping)
			{
				inFrames += Frame(Frame::Ping, packet.body, false);
				inSize += packet.body.size();
			}
			else if(packet.type == ZhttpRequestPacket::Pong)
			{
				inFrames += Frame(Frame::Pong, packet.body, false);
				inSize += packet.body.size();
			}

			if(packet.credits > 0)
			{
				outCredits += packet.credits;
				if(outCredits > 0)
				{
					// try to write anything that was waiting on credits
					QPointer<QObject> self = this;
					tryWrite();
					if(!self)
						return;
				}
			}

			emit q->readyRead();
		}
		else if(packet.type == ZhttpRequestPacket::Close)
		{
			handlePeerClose(packet.code);
		}
		else if(packet.type == ZhttpRequestPacket::Credit)
		{
			if(packet.credits > 0)
			{
				outCredits += packet.credits;
				tryWrite();
			}
		}
		else if(packet.type == ZhttpRequestPacket::KeepAlive)
		{
			// nothing to do
		}
		else
		{
			log_debug("zws server: unsupported packet type id=%s type=%d", packet.id.data(), (int)packet.type);
		}
	}
	void CBAWMeshWriter::exportAsBlob<asset::IMeshDataFormatDesc<asset::ICPUBuffer> >(asset::IMeshDataFormatDesc<asset::ICPUBuffer>* _obj, uint32_t _headerIdx, io::IWriteFile* _file, SContext& _ctx)
	{
        asset::MeshDataFormatDescBlobV1 data(_obj);

		tryWrite(&data, _file, _ctx, sizeof(data), _headerIdx, asset::EWF_NONE);
	}
Ejemplo n.º 23
0
void
RemotePluginServer::dispatchControlEvents()
{    
    RemotePluginOpcode opcode = RemotePluginNoOpcode;
    static float *parameterBuffer = 0;

    tryRead(m_controlRequestFd, &opcode, sizeof(RemotePluginOpcode));

    switch (opcode) {

    case RemotePluginGetVersion:
	writeFloat(m_controlResponseFd, getVersion());
	break;

    case RemotePluginGetName:
	writeString(m_controlResponseFd, getName());
	break;

    case RemotePluginGetMaker:
	writeString(m_controlResponseFd, getMaker());
	break;
    
    case RemotePluginTerminate:
	terminate();
	break;
    
    case RemotePluginGetInputCount:
	m_numInputs = getInputCount();
	writeInt(m_controlResponseFd, m_numInputs);
	break;

    case RemotePluginGetOutputCount:
	m_numOutputs = getOutputCount();
	writeInt(m_controlResponseFd, m_numOutputs);
	break;

    case RemotePluginGetParameterCount:
	writeInt(m_controlResponseFd, getParameterCount());
	break;
	
    case RemotePluginGetParameterName:
	writeString(m_controlResponseFd, getParameterName(readInt(m_controlRequestFd)));
	break;
    
    case RemotePluginGetParameter:
	writeFloat(m_controlResponseFd, getParameter(readInt(m_controlRequestFd)));
	break;
    
    case RemotePluginGetParameterDefault:
	writeFloat(m_controlResponseFd, getParameterDefault(readInt(m_controlRequestFd)));
	break;

    case RemotePluginGetParameters:
    {
	if (!parameterBuffer) {
	    parameterBuffer = new float[getParameterCount()];
	}
	int p0 = readInt(m_controlRequestFd);
	int pn = readInt(m_controlRequestFd);
	getParameters(p0, pn, parameterBuffer);
	tryWrite(m_controlResponseFd, parameterBuffer, (pn - p0 + 1) * sizeof(float));
	break;
    }

    case RemotePluginHasMIDIInput:
    {
	bool m = hasMIDIInput();
	tryWrite(m_controlResponseFd, &m, sizeof(bool));
	break;
    }
       
    case RemotePluginGetProgramCount:
	writeInt(m_controlResponseFd, getProgramCount());
	break;

    case RemotePluginGetProgramName:
	writeString(m_controlResponseFd, getProgramName(readInt(m_controlRequestFd)));
	break;

    case RemotePluginIsReady:
    {
	if (!m_shm) sizeShm();
	bool b(isReady());
	std::cerr << "isReady: returning " << b << std::endl;
	tryWrite(m_controlResponseFd, &b, sizeof(bool));
    }

    case RemotePluginSetDebugLevel:
    {
	RemotePluginDebugLevel newLevel = m_debugLevel;
	tryRead(m_controlRequestFd, &newLevel, sizeof(RemotePluginDebugLevel));
	setDebugLevel(newLevel);
	m_debugLevel = newLevel;
	break;
    }

    case RemotePluginWarn:
    {
	bool b = warn(readString(m_controlRequestFd));
	tryWrite(m_controlResponseFd, &b, sizeof(bool));
	break;
    }

    case RemotePluginShowGUI:
    {
	showGUI(readString(m_controlRequestFd));
	break;
    }

    case RemotePluginHideGUI:
    {
	hideGUI();
	break;
    }

    //Deryabin Andrew: vst chunks support
    case RemotePluginGetVSTChunk:
    {
        std::vector<char> chunk = getVSTChunk();
        writeRaw(m_controlResponseFd, chunk);
        break;
    }

    case RemotePluginSetVSTChunk:
    {
        std::vector<char> chunk = readRaw(m_controlRequestFd);
        setVSTChunk(chunk);
        break;
    }
    //Deryabin Andrew: vst chunks support: end code

    case RemotePluginNoOpcode:
	break;

    case RemotePluginReset:
	reset();
	break;

    default:
	std::cerr << "WARNING: RemotePluginServer::dispatchControlEvents: unexpected opcode "
		  << opcode << std::endl;
    }
}