コード例 #1
0
void
CTCPSocket::shutdownInput()
{
	bool useNewJob = false;
	{
		CLock lock(&m_mutex);

		// shutdown socket for reading
		try {
			ARCH->closeSocketForRead(m_socket);
		}
		catch (XArchNetwork&) {
			// ignore
		}

		// shutdown buffer for reading
		if (m_readable) {
			sendEvent(getInputShutdownEvent());
			onInputShutdown();
			useNewJob = true;
		}
	}
	if (useNewJob) {
		setJob(newJob());
	}
}
コード例 #2
0
void
CPacketStreamFilter::filterEvent(const CEvent& event)
{
    if (event.getType() == getInputReadyEvent()) {
        CLock lock(&m_mutex);
        if (!readMore()) {
            return;
        }
    }
    else if (event.getType() == getInputShutdownEvent()) {
        // discard this if we have buffered data
        CLock lock(&m_mutex);
        m_inputShutdown = true;
        if (m_size != 0) {
            return;
        }
    }

    // pass event
    CStreamFilter::filterEvent(event);
}
コード例 #3
0
UInt32
CPacketStreamFilter::read(void* buffer, UInt32 n)
{
    if (n == 0) {
        return 0;
    }

    CLock lock(&m_mutex);

    // if not enough data yet then give up
    if (!isReadyNoLock()) {
        return 0;
    }

    // read no more than what's left in the buffered packet
    if (n > m_size) {
        n = m_size;
    }

    // read it
    if (buffer != NULL) {
        memcpy(buffer, m_buffer.peek(n), n);
    }
    m_buffer.pop(n);
    m_size -= n;

    // get next packet's size if we've finished with this packet and
    // there's enough data to do so.
    readPacketSize();

    if (m_inputShutdown && m_size == 0) {
        EVENTQUEUE->addEvent(CEvent(getInputShutdownEvent(),
                                    getEventTarget(), NULL));
    }

    return n;
}
コード例 #4
0
ISocketMultiplexerJob*
CTCPSocket::serviceConnected(ISocketMultiplexerJob* job,
				bool read, bool write, bool error)
{
	CLock lock(&m_mutex);

	if (error) {
		sendEvent(getDisconnectedEvent());
		onDisconnected();
		return newJob();
	}

	bool needNewJob = false;

	if (write) {
		try {
			// write data
			UInt32 n = m_outputBuffer.getSize();
			const void* buffer = m_outputBuffer.peek(n);
			n = (UInt32)ARCH->writeSocket(m_socket, buffer, n);

			// discard written data
			if (n > 0) {
				m_outputBuffer.pop(n);
				if (m_outputBuffer.getSize() == 0) {
					sendEvent(getOutputFlushedEvent());
					m_flushed = true;
					m_flushed.broadcast();
					needNewJob = true;
				}
			}
		}
		catch (XArchNetworkShutdown&) {
			// remote read end of stream hungup.  our output side
			// has therefore shutdown.
			onOutputShutdown();
			sendEvent(getOutputShutdownEvent());
			if (!m_readable && m_inputBuffer.getSize() == 0) {
				sendEvent(getDisconnectedEvent());
				m_connected = false;
			}
			needNewJob = true;
		}
		catch (XArchNetworkDisconnected&) {
			// stream hungup
			onDisconnected();
			sendEvent(getDisconnectedEvent());
			needNewJob = true;
		}
		catch (XArchNetwork& e) {
			// other write error
			LOG((CLOG_WARN "error writing socket: %s", e.what().c_str()));
			onDisconnected();
			sendEvent(getOutputErrorEvent());
			sendEvent(getDisconnectedEvent());
			needNewJob = true;
		}
	}

	if (read && m_readable) {
		try {
			UInt8 buffer[4096];
			size_t n = ARCH->readSocket(m_socket, buffer, sizeof(buffer));
			if (n > 0) {
				bool wasEmpty = (m_inputBuffer.getSize() == 0);

				// slurp up as much as possible
				do {
					m_inputBuffer.write(buffer, n);
					n = ARCH->readSocket(m_socket, buffer, sizeof(buffer));
				} while (n > 0);

				// send input ready if input buffer was empty
				if (wasEmpty) {
					sendEvent(getInputReadyEvent());
				}
			}
			else {
				// remote write end of stream hungup.  our input side
				// has therefore shutdown but don't flush our buffer
				// since there's still data to be read.
				sendEvent(getInputShutdownEvent());
				if (!m_writable && m_inputBuffer.getSize() == 0) {
					sendEvent(getDisconnectedEvent());
					m_connected = false;
				}
				m_readable = false;
				needNewJob = true;
			}
		}
		catch (XArchNetworkDisconnected&) {
			// stream hungup
			sendEvent(getDisconnectedEvent());
			onDisconnected();
			needNewJob = true;
		}
		catch (XArchNetwork& e) {
			// ignore other read error
			LOG((CLOG_WARN "error reading socket: %s", e.what().c_str()));
		}
	}

	return needNewJob ? newJob() : job;
}