Пример #1
0
void Server::checkAndDispatchEpoll(int epollMillis) {
    constexpr int maxEvents = 256;
    epoll_event events[maxEvents];

    std::list<Connection*> toBeDeleted;
    int numEvents = epoll_wait(_epollFd, events, maxEvents, epollMillis);
    if (numEvents == -1) {
        if (errno != EINTR) {
            LS_ERROR(_logger, "Error from epoll_wait: " << getLastError());
        }
        return;
    }
    if (numEvents == maxEvents) {
        static time_t lastWarnTime = 0;
        time_t now = time(nullptr);
        if (now - lastWarnTime >= 60) {
            LS_WARNING(_logger, "Full event queue; may start starving connections. "
                    "Will warn at most once a minute");
            lastWarnTime = now;
        }
    }
    for (int i = 0; i < numEvents; ++i) {
        if (events[i].data.ptr == this) {
            if (events[i].events & ~EPOLLIN) {
                LS_SEVERE(_logger, "Got unexpected event on listening socket ("
                        << EventBits(events[i].events) << ") - terminating");
                _terminate = true;
                break;
            }
            handleAccept();
        } else if (events[i].data.ptr == &_eventFd) {
            if (events[i].events & ~EPOLLIN) {
                LS_SEVERE(_logger, "Got unexpected event on management pipe ("
                        << EventBits(events[i].events) << ") - terminating");
                _terminate = true;
                break;
            }
            handlePipe();
        } else {
            auto connection = reinterpret_cast<Connection*>(events[i].data.ptr);
            if (handleConnectionEvents(connection, events[i].events) == Close) {
                toBeDeleted.push_back(connection);
            }
        }
    }
    // The connections are all deleted at the end so we've processed any other subject's
    // closes etc before we call onDisconnect().
    for (auto it = toBeDeleted.begin(); it != toBeDeleted.end(); ++it) {
        auto connection = *it;
        if (_connections.find(connection) == _connections.end()) {
            LS_SEVERE(_logger, "Attempt to delete connection we didn't know about: " << (void*)connection
                    << formatAddress(connection->getRemoteAddress()));
            _terminate = true;
            break;
        }
        LS_DEBUG(_logger, "Deleting connection: " << formatAddress(connection->getRemoteAddress()));
        delete connection;
    }
}
Пример #2
0
QString SpimView::formatMemoryContents(mem_addr from, mem_addr to)
{
    mem_addr i = ROUND_UP(from, BYTES_PER_WORD);
    QString windowContents = formatPartialQuadWord(i, to);
    i = ROUND_UP(i, BYTES_PER_LINE); // Next quadword

    for ( ; i < to; )
    {
        mem_word val;

        /* Count consecutive zero words */
        int j;
        for (j = 0; (i + (uint32) j * BYTES_PER_WORD) < to; j += 1)
	{
            val = read_mem_word(i + (uint32) j * BYTES_PER_WORD);
            if (val != 0)
	    {
                break;
	    }
	}

        if (j >= 4)
	{
            /* Block of 4 or more zero memory words: */
            windowContents += QString("[") % formatAddress(i)
                % QString("]..[") % formatAddress(i + (uint32) j * BYTES_PER_WORD - 1)
                % QString("]") % nnbsp(2) % QString("00000000<br>");

            i = i + (uint32) j * BYTES_PER_WORD;
            windowContents += formatPartialQuadWord(i, to);
            i = ROUND_UP(i, BYTES_PER_LINE); // Next quadword
	}
        else
	{
            /* Fewer than 4 zero words, print them on a single line: */
            windowContents += QString("[") % formatAddress(i) % "]" % nnbsp(2);
            mem_addr j = i;
            do
	    {
                val = read_mem_word(i);
                windowContents += nnbsp(2) % formatWord(val, st_dataSegmentDisplayBase);
                i += BYTES_PER_WORD;
	    }
            while ((i % BYTES_PER_LINE) != 0 && i < to);

            windowContents += nnbsp(2) % formatAsChars(j, i) % QString("<br>");
	}
    }
    return windowContents;
}
Пример #3
0
void Server::handleAccept() {
    sockaddr_in address;
    socklen_t addrLen = sizeof(address);
    int fd = ::accept(_listenSock,
            reinterpret_cast<sockaddr*>(&address),
            &addrLen);
    if (fd == -1) {
        LS_ERROR(_logger, "Unable to accept: " << getLastError());
        return;
    }
    if (!configureSocket(fd)) {
        ::close(fd);
        return;
    }
    LS_INFO(_logger, formatAddress(address) << " : Accepted on descriptor " << fd);
    Connection* newConnection = new Connection(_logger, *this, fd, address);
    epoll_event event = { EPOLLIN, { newConnection } };
    if (epoll_ctl(_epollFd, EPOLL_CTL_ADD, fd, &event) == -1) {
        LS_ERROR(_logger, "Unable to add socket to epoll: " << getLastError());
        delete newConnection;
        ::close(fd);
        return;
    }
    _connections.insert(std::make_pair(newConnection, time(nullptr)));
}
QVariant DecisionDecisionTableModel::data(const QModelIndex &index, int role) const
{
    if(!index.isValid())
        return QVariant();
    const marketDecision *decision = (const marketDecision *) index.internalPointer();

    switch(role)
    {
    case Qt::DisplayRole:
        switch(index.column())
        {
        case Address:
            return formatAddress(decision);
        case Prompt:
            return formatPrompt(decision);
        case EventOverBy:
            return QVariant((int)decision->eventOverBy);
        case IsScaled:
            return formatIsScaled(decision);
        case Minimum:
            return QVariant((double)decision->min*1e-8);
        case Maximum:
            return QVariant((double)decision->max*1e-8);
        case AnswerOptional:
            return formatAnswerOptional(decision);
        case Hash:
            return formatHash(decision);
        default:
            ;
        }
        break;
    case AddressRole:
        return formatAddress(decision);
    case PromptRole:
        return formatPrompt(decision);
    case Qt::TextAlignmentRole:
        return column_alignments[index.column()];
    }
    return QVariant();
}
Пример #5
0
Server::NewState Server::handleConnectionEvents(Connection* connection, uint32_t events) {
    if (events & ~(EPOLLIN|EPOLLOUT|EPOLLHUP|EPOLLERR)) {
        LS_WARNING(_logger, "Got unhandled epoll event (" << EventBits(events) << ") on connection: "
                << formatAddress(connection->getRemoteAddress()));
        return Close;
    } else if (events & EPOLLERR) {
        LS_INFO(_logger, "Error on socket (" << EventBits(events) << "): "
                << formatAddress(connection->getRemoteAddress()));
        return Close;
    } else if (events & EPOLLHUP) {
        LS_DEBUG(_logger, "Graceful hang-up (" << EventBits(events) << ") of socket: "
                << formatAddress(connection->getRemoteAddress()));
        return Close;
    } else {
        if (events & EPOLLOUT) {
            connection->handleDataReadyForWrite();
        }
        if (events & EPOLLIN) {
            connection->handleDataReadyForRead();
        }
    }
    return KeepOpen;
}
Пример #6
0
void dataTextEdit::changeValue()
{
    QTextCursor cursor;
    mem_addr addr = addrFromPos(&cursor);
    if (addr != 0)
    {
        int base = Window->DataDisplayBase();
        QString val = promptForNewValue("New Contents for " + formatAddress(addr), &base);
        bool ok;
        int newMemVal = val.toInt(&ok, base);
        if (ok)
        {
            set_mem_word(addr, newMemVal);
        }

        Window->DisplayDataSegments(true);
    }
}
Пример #7
0
void Server::processEventQueue() {
    runExecutables();
    time_t now = time(nullptr);
    if (now < _nextDeadConnectionCheck) return;
    std::list<Connection*> toRemove;
    for (auto it = _connections.cbegin(); it != _connections.cend(); ++it) {
        time_t numSecondsSinceConnection = now - it->second;
        auto connection = it->first;
        if (connection->bytesReceived() == 0
            && numSecondsSinceConnection >= _lameConnectionTimeoutSeconds) {
            LS_INFO(_logger, formatAddress(connection->getRemoteAddress())
                    << " : Killing lame connection - no bytes received after "
                             << numSecondsSinceConnection << "s");
            toRemove.push_back(connection);
        }
    }
    for (auto it = toRemove.begin(); it != toRemove.end(); ++it) {
        delete *it;
    }
}
Пример #8
0
QString SpimView::formatPartialQuadWord(mem_addr from, mem_addr to)
{
    QString windowContents = QString("");

    if ((from % BYTES_PER_LINE) != 0 && from < to)
    {
        windowContents += QString("[") % formatAddress(from) % QString("]") % nnbsp(2);

        mem_addr a;
        for (a = from; (a % BYTES_PER_LINE) != 0; a += BYTES_PER_WORD)
	{
            mem_word val = read_mem_word(a);
            windowContents += nnbsp(2) % formatWord(val, st_dataSegmentDisplayBase);
	}

        windowContents += formatAsChars(from, a) % QString("<br>");
    }

    return windowContents;
}
Пример #9
0
std::string Server::getStatsDocument() const {
    std::ostringstream doc;
    doc << "clear();" << std::endl;
    for (auto it = _connections.begin(); it != _connections.end(); ++it) {
        doc << "connection({";
        auto connection = it->first;
        jsonKeyPairToStream(doc,
                "since", EpochTimeAsLocal(it->second),
                "fd", connection->getFd(),
                "id", reinterpret_cast<uint64_t>(connection),
                "uri", connection->getRequestUri(),
                "addr", formatAddress(connection->getRemoteAddress()),
                "user", connection->credentials() ?
                        connection->credentials()->username : "******",
                "input", connection->inputBufferSize(),
                "read", connection->bytesReceived(),
                "output", connection->outputBufferSize(),
                "written", connection->bytesSent()
        );
        doc << "});" << std::endl;
    }
    return doc.str();
}
Пример #10
0
void Server::processEventQueue() {
    for (;;) {
        std::shared_ptr<Runnable> runnable = popNextRunnable();
        if (!runnable) break;
        runnable->run();
    }
    time_t now = time(NULL);
    if (now >= _nextDeadConnectionCheck) {
        std::list<Connection*> toRemove;
        for (auto it = _connections.cbegin(); it != _connections.cend(); ++it) {
            time_t numSecondsSinceConnection = now - it->second;
            auto connection = it->first;
            if (connection->bytesReceived() == 0 && numSecondsSinceConnection >= _lameConnectionTimeoutSeconds) {
                LS_INFO(_logger, formatAddress(connection->getRemoteAddress())
                        << " : Killing lame connection - no bytes received after " << numSecondsSinceConnection << "s");
                toRemove.push_back(connection);
            }
        }
        for (auto it = toRemove.begin(); it != toRemove.end(); ++it) {
            delete *it;
        }
    }
}
Пример #11
0
int session(const struct sockaddr* modem_address, socklen_t modem_address_length, uint32_t router_heartbeat_interval)
{
	int ret = -1;
	char str_address[FORMATADDRESS_LEN] = {0};

	/* First we must initialise, RFC 8175 section 7.2 */
	int s = socket(modem_address->sa_family,SOCK_STREAM,0);
	if (s == -1)
	{
		printf("Failed to create socket: %s\n",strerror(errno));
		return -1;
	}

	printf("Connecting to modem at %s\n",formatAddress(modem_address,str_address,sizeof(str_address)));

	/* Connect to the modem */
	if (connect(s,modem_address,modem_address_length) == -1)
	{
		printf("Failed to connect socket: %s\n",strerror(errno));
	}
	else if (send_session_init_message(s,router_heartbeat_interval))
	{
		uint8_t* msg = NULL;
		ssize_t received;

		printf("Waiting for Session Initialization Response message\n");

		/* Receive a Session Initialization Response message */
		received = recv_message(s,&msg);
		if (received == -1)
			printf("Failed to receive from TCP socket: %s\n",strerror(errno));
		else if (received == 0)
			printf("Modem disconnected TCP session\n");
		else
		{
			printf("Received possible Session Initialization Response message (%u bytes)\n",(unsigned int)received);

			/* Check it's a valid Session Initialization Response message */
			if (check_session_init_resp_message(msg,received) == DLEP_SC_SUCCESS)
			{
				uint32_t modem_heartbeat_interval = 60000;
				enum dlep_status_code init_sc = DLEP_SC_SUCCESS;

				enum dlep_status_code sc = parse_session_init_resp_message(msg+4,received-4,&modem_heartbeat_interval,&init_sc);
				if (sc != DLEP_SC_SUCCESS)
				{
					send_session_term(s,sc,&msg,modem_heartbeat_interval);
				}
				else if (init_sc != DLEP_SC_SUCCESS)
				{
					printf("Non-zero Status data item in Session Initialization Response message: %u, Terminating\n",init_sc);

					ret = send_session_term(s,DLEP_SC_SHUTDOWN,&msg,modem_heartbeat_interval);
				}
				else
				{
					printf("Moving to 'in-session' state\n");

					ret = in_session(s,&msg,modem_heartbeat_interval,router_heartbeat_interval);
				}
			}
		}

		free(msg);
	}

	close(s);

	return ret;
}
Пример #12
0
QString formatSegLabel(QString segName, mem_addr low, mem_addr high)
{
    return QString("<center><b>") % segName
        % QString(" [") % formatAddress(low) % QString("]..[") % formatAddress(high)
        % QString("]</b></center>");
}