/*----------------------------------------------------------------------------*
 *  NAME
 *      uartTxDataCallback
 *
 *  DESCRIPTION
 *      This is an internal callback function (of type uart_data_out_fn) that
 *      will be called by the UART driver when data transmission over the UART
 *      is finished. See DebugInit in the Firmware Library documentation for
 *      details.
 *
 * RETURNS
 *      Nothing
 *----------------------------------------------------------------------------*/
static void uartTxDataCallback(void)
{
    /* This has been added so that the UART port is open for sending the data */
    /* One may add another queue to handle the Tx Data separately */
    /* Send any pending data waiting to be sent */
    sendPendingData();
}
/*----------------------------------------------------------------------------*
 *  NAME
 *      SendDataToUart
 *
 *  DESCRIPTION
 *      Sends the received data over UART.
 *
 *  RETURNS
 *      Nothing
 *
 *----------------------------------------------------------------------------*/
extern void SendDataToUart(uint8 *data, uint16 size)
{
     /* We initially attempt to directly write to the UART and from there on
     * we send the data using callback mechanism, whenever the UART is ready
     * to accept more incoming data. This is to avoid data loss. The data is
     * buffered and sent to UART using callback mechanism.
     */
    if(!g_trigger_write_callback)
    {
        UartWrite(data, size);
        g_trigger_write_callback = TRUE;
        return;
    }

    /* Queue the incoming data to the queue. will be written when UART is ready
     */  
    if(g_trigger_write_callback)
    {
        /* First copy all the bytes received into the byte queue */
        BQSafeQueueBytes((const uint8 *)data, size,RECV_QUEUE_ID);

        /*Send Pending Data */
        sendPendingData();
    }
}
void SocketThread::run()
{
	{
	queryTime.restart();
	if(isLogEnabled)logThread->writeLog("SocketThread Started");
	sslSocket=new QSslSocket;
	connect(this,SIGNAL(sendToApiSignal(QByteArray, QByteArray)),this,SLOT(sendToApiSlot(QByteArray, QByteArray)));
	connect(this,SIGNAL(reconnectApiSignal()),this,SLOT(reconnectApiSlot()));
	connect(sslSocket,SIGNAL(readyRead()),SLOT(readSocket()));

	secondTimer=new QTimer;
	connect(secondTimer,SIGNAL(timeout()),this,SLOT(secondSlot()));

	if(useSSL)sslSocket->connectToHostEncrypted(hostName, 443);
		else  sslSocket->connectToHost(hostName, 80);
	sslSocket->waitForConnected();
	if(isLogEnabled)
	{
		logThread->writeLog("SSL Socket state:"+sslSocket->errorString().toAscii()+". Supported: "+QByteArray::number(sslSocket->supportsSsl()));
	}
	
	secondTimer->start(100);
	sendPendingData();
	}
	exec();
}
Beispiel #4
0
void Gosu::CommSocket::update()
{
    sendPendingData();

    if (!connected())
        return;

    for (;;)
    {
        char buffer[1024];
        int received = ::recv(pimpl->socket.handle(), buffer, sizeof buffer, 0);

        if (received > 0 && received <= static_cast<int>(sizeof buffer))
        {
            // Data arrived and fit into the buffer.
            pimpl->appendBuffer(buffer, received, onReceive);
        }
        else if (received == 0)
        {
            // The other side has gracefully closed the connection.
            disconnect();
            return;
        }
        else if (received == SOCKET_ERROR)
        {
            switch (lastSocketError())
            {
                // Arriving data didn't fit into the buffer.
                case GOSU_SOCK_ERR(EMSGSIZE):
                    pimpl->appendBuffer(buffer, sizeof buffer, onReceive);
                    break;

                // There simply was no data.
                case GOSU_SOCK_ERR(EWOULDBLOCK):
                    return;

                // Connection was reset or is invalid.
                case GOSU_SOCK_ERR(ENETDOWN):
                case GOSU_SOCK_ERR(ENOTCONN):
                case GOSU_SOCK_ERR(ENETRESET):
                case GOSU_SOCK_ERR(ECONNABORTED):
                case GOSU_SOCK_ERR(ETIMEDOUT):
                case GOSU_SOCK_ERR(ECONNRESET):
				#ifndef GOSU_IS_WIN
				// UNIX specific, rare error
                case GOSU_SOCK_ERR(EPIPE):
				#endif
                    disconnect();
                    return;

                // Everything else is unexpected.
                default:
                    throwLastSocketError();
            }
        }
        else assert(false);
    }
}
void SocketStreamHandle::writeReady()
{
    // We no longer have buffered data, so stop waiting for the socket to be writable.
    if (!bufferedAmount()) {
        stopWaitingForSocketWritability();
        return;
    }

    sendPendingData();
}
Beispiel #6
0
void SocketStreamHandle::writeStreamCallback(CFStreamEventType type)
{
    switch(type) {
    case kCFStreamEventNone:
        break;
    case kCFStreamEventOpenCompleted:
        break;
    case kCFStreamEventHasBytesAvailable:
        ASSERT_NOT_REACHED();
        break;
    case kCFStreamEventCanAcceptBytes: {
        // Possibly, a spurious event from CONNECT handshake.
        if (!CFWriteStreamCanAcceptBytes(m_writeStream.get()))
            return;

        if (m_connectingSubstate == WaitingForCredentials)
            break;

        if (m_connectingSubstate == WaitingForConnect) {
            m_connectingSubstate = Connected;
            m_state = Open;

            RefPtr<SocketStreamHandle> protect(this); // The client can close the handle, potentially removing the last reference.
            m_client->didOpen(this);
            break;
        }

        ASSERT(m_state == Open);
        ASSERT(m_connectingSubstate == Connected);

        sendPendingData();
        break;
    }
    case kCFStreamEventErrorOccurred: {
#ifndef BUILDING_ON_TIGER
        RetainPtr<CFErrorRef> error(AdoptCF, CFWriteStreamCopyError(m_writeStream.get()));
        reportErrorToClient(error.get());
#else
        CFStreamError error = CFWriteStreamGetError(m_writeStream.get());
        m_client->didFail(this, SocketStreamError(error.error)); // FIXME: Provide a sensible error.
#endif
        break;
    }
    case kCFStreamEventEndEncountered:
        // FIXME: Currently, we handle closing in read callback, but these can come independently (e.g. a server can stop listening, but keep sending data).
        break;
    }
}
void SocketThread::readSocket()
{
	QByteArray currentAllData=sslSocket->readAll();
	while(currentAllData.size())
	{
		QByteArray currentData;
		int lrlnlrln=currentAllData.indexOf("\r\n\r\n");

		if(lrlnlrln>-1){currentData=currentAllData.left(lrlnlrln-1);currentAllData.remove(0,lrlnlrln+4);}
		else {currentData=currentAllData;currentAllData.clear();}
		if(currentData.size()<2)continue;

		if(currentData.startsWith("HTTP"))
		{
			if(currentData.startsWith("HTTP/1.1 50")&&!currentData.startsWith("HTTP/1.1 500")){emit apiDown();waitingNewData=false;return;}
			if(waitingNewData)
			{
				checkDataAndSend(&dataBuffer);
				if(isLogEnabled&&dataBuffer.size())logThread->writeLog("Ignored Corrupt Data: "+dataBuffer);
				dataBuffer.clear();
				waitingNewData=false;
			}
			continue;
		}

		if(currentData.right(2)=="\r\n")currentData.remove(currentData.size()-2,2);

		int firstlRlN=currentData.indexOf("\r\n");
		if(firstlRlN>-1&&currentData.size()>=firstlRlN+2)currentData.remove(0,firstlRlN+2);

		checkDataAndSend(&currentData);
		if(!currentData.isEmpty())
		{
			dataBuffer.append(currentData);
			waitingNewData=true;
			checkDataAndSend(&dataBuffer);
			if(dataBuffer.isEmpty())
			{
				waitingNewData=false;
				sendPendingData();
			}
		}
	}
}
void SocketStreamHandle::writeStreamCallback(CFStreamEventType type)
{
    switch(type) {
    case kCFStreamEventNone:
        break;
    case kCFStreamEventOpenCompleted:
        break;
    case kCFStreamEventHasBytesAvailable:
        ASSERT_NOT_REACHED();
        break;
    case kCFStreamEventCanAcceptBytes: {
        // Possibly, a spurious event from CONNECT handshake.
        if (!CFWriteStreamCanAcceptBytes(m_writeStream.get()))
            return;

        if (m_connectingSubstate == WaitingForCredentials)
            break;

        if (m_connectingSubstate == WaitingForConnect) {
            m_connectingSubstate = Connected;
            m_state = Open;
            m_client->didOpenSocketStream(this);
            break;
        }

        ASSERT(m_state == Open);
        ASSERT(m_connectingSubstate == Connected);

        sendPendingData();
        break;
    }
    case kCFStreamEventErrorOccurred: {
        RetainPtr<CFErrorRef> error(AdoptCF, CFWriteStreamCopyError(m_writeStream.get()));
        reportErrorToClient(error.get());
        break;
    }
    case kCFStreamEventEndEncountered:
        // FIXME: Currently, we handle closing in read callback, but these can come independently (e.g. a server can stop listening, but keep sending data).
        break;
    }
}
Beispiel #9
0
// private methods
void SocketStreamHandle::processMessageOnMainThread(StreamMessage msg)
{
    switch (msg) {
        case DidOpen:
            ASSERT(m_state == Open);
            if (m_client)
                m_client->didOpenSocketStream(this);
            break;
        case DidFail:
            ASSERT(m_curl_code != CURLE_OK);
            LOG_CONNECT(Network, "SocketStreamHandleCurl: DidFail, error %d (%s), curl error buffer: %s [%p][thread=%d]\n", m_curl_code, curl_easy_strerror(m_curl_code), m_curl_error_buffer, this, GetCurrentThreadId());
            if (m_client)
                m_client->didFailSocketStream(this, SocketStreamError(m_curl_code, m_url.isEmpty() ? String() : m_url.string()));
            break;
        case DidReceiveData:
            didReceiveData();
            break;
        case DidSelectForWrite: {
            deref(); // this balances the ref() when spinning up the send wait thread.
            // LOG(Network, "SocketStreamHandleCurl: DidSelectForWrite [%p][thread=%d]\n", this, GetCurrentThreadId());
            if (!m_platformCloseRequested) {
                if (m_curl_code == CURLE_OK) {
                    sendPendingData();
                }
                else if (m_client) {
                    m_client->didFailSocketStream(this, SocketStreamError(m_curl_code, m_url.isEmpty() ? String() : m_url.string()));
                }
            }
            } break;
        case DidClose:
            disconnect();
            break;
        case DidStopRecvLoop:
            deref(); // this balances the ref() in the constructor.
            break;
    }
    deref();
}
void
SocketStreamHandleServer::progressTimerFired()
{
    switch (m_progressState) {
    case EError:
        if (m_client)
            m_client->didFailSocketStream(reinterpret_cast<SocketStreamHandle*>(this), SocketStreamError(-1));
        break;

    case EConnectingDest:
        break;
#if 0
    case EConnectingProxy:
    {
        char buf[1024] = {0};
        fd_set rd;
        FD_ZERO(&rd);
        FD_SET(m_socket, &rd);
        struct timeval tv = {0};
        if (wkcNetSelectPeer(m_socket+1, &rd, NULL, NULL, &tv)==0) {
            m_progressTimer.startOneShot(0.1);
            break;
        }
        int len = wkcNetRecvPeer(m_socket, buf, sizeof(buf), 0);
        if (len<=0) {
            m_progressTimer.startOneShot(0.1);
            break;
        }
        String result(buf);
        if (result.find("Connection Established", 0, false)) {
            m_progressState = EConnected;
            m_progressTimer.startOneShot(0.1);
        } else {
            m_progressState = EError;
            m_progressTimer.startOneShot(0.1);
        }
        break;
    }
#endif
    case EConnected:
        m_state = Open;
        m_progressState = EReady;
        if (m_client)
            m_client->didOpenSocketStream(reinterpret_cast<SocketStreamHandle*>(this));
        m_progressTimer.startOneShot(0.1);
        break;

    case EReady:
    {
        char buf[1024] = {0};
        do {
            fd_set rd, wd;
            FD_ZERO(&rd);
            FD_ZERO(&wd);
            FD_SET(m_socket, &rd);
            FD_SET(m_socket, &wd);
            struct timeval tv = {0};
            int ret = wkcNetSelectPeer(m_socket+1, &rd, &wd, NULL, &tv);
            if (ret == 0 || (!FD_ISSET(m_socket, &rd) && !bufferedAmount()))
                break;
            if (FD_ISSET(m_socket, &rd)) {
                int len = wkcNetRecvPeer(m_socket, buf, sizeof(buf), 0);
                if (len<=0)
                    break;
                if (m_client)
                    m_client->didReceiveSocketStreamData(reinterpret_cast<SocketStreamHandle*>(this), buf, len);
            }
            if (bufferedAmount()) {
                if (FD_ISSET(m_socket, &wd)) {
                    if (!sendPendingData()) {
                        m_progressState = EError;
                        break;
                    }
                }
            }
        } while (1);
        m_progressTimer.startOneShot(0.1);
        break;
    }

    case ERequestClose:
        if (m_client)
            m_client->didCloseSocketStream(reinterpret_cast<SocketStreamHandle*>(this));
        m_state = Closed;
        break;

    default:
        break;
    }
}
void SocketThread::secondSlot()
{
	checkSocketConnected();
	if(queryTime.elapsed()>800)sendPendingData();
}
Beispiel #12
0
void SocketStreamHandle::notifyReadyToSendData()
{
    sendPendingData();
}