Пример #1
0
void NetworkTransaction::SetConnectionLost()
{
	cs = NULL;
	FreePbuf();
	for (NetworkTransaction *rs = nextWrite; rs != NULL; rs = rs->nextWrite)
	{
		rs->cs = NULL;
	}
}
Пример #2
0
void RequestState::SetConnectionLost()
{
	hs = NULL;
	FreePbuf();
	for (RequestState *rs = nextWrite; rs != NULL; rs = rs->nextWrite)
	{
		rs->hs = NULL;
	}
}
Пример #3
0
// This method should be called if we don't want to send data to the client and if we
// don't want to interfere with the connection state. May also be called from ISR!
void NetworkTransaction::Discard()
{
	// Can we do anything?
	if (status == released)
	{
		// No - don't free up released items multiple times
		return;
	}

	// Free up some resources
	FreePbuf();

	if (fileBeingSent != nullptr)
	{
		fileBeingSent->Close();
		fileBeingSent = nullptr;
	}

	OutputBuffer::ReleaseAll(sendBuffer);
	sendStack->ReleaseAll();

	// Unlink this transactions from the list of ready transactions and free it. It is then appended to the list of
	// free transactions because we don't want to risk reusing it when the ethernet ISR processes incoming data
	NetworkTransaction *previous = nullptr;
	for(NetworkTransaction *item = reprap.GetNetwork().readyTransactions; item != nullptr; item = item->next)
	{
		if (item == this)
		{
			if (previous == nullptr)
			{
				reprap.GetNetwork().readyTransactions = next;
			}
			else
			{
				previous->next = next;
			}
			break;
		}
		previous = item;
	}
	reprap.GetNetwork().AppendTransaction(&reprap.GetNetwork().freeTransactions, this);
	bool callDisconnectHandler = (cs != nullptr && status == disconnected);
	status = released;

	// Call disconnect event if this transaction indicates a graceful disconnect and if the connection
	// still persists (may not be the case if a RST packet was received before)
	if (callDisconnectHandler)
	{
		if (reprap.Debug(moduleNetwork))
		{
			reprap.GetPlatform().Message(UsbMessage, "Network: Discard() is handling a graceful disconnect\n");
		}
		reprap.GetNetwork().ConnectionClosed(cs, false);
	}
}
Пример #4
0
// Call this to perform some networking tasks while processing deferred requests,
// and to move this transaction and all transactions that are associated with its
// connection to the end of readyTransactions. There are three ways to do this:
//
// 1) DeferOnly: Do not modify any of the processed data and don't send an ACK.
//               This will ensure that zero-window packets are sent back to the client
// 2) ResetData: Reset the read pointers and acknowledge that the data has been processed
// 3) DiscardData: Free the processed data, acknowledge it and append this transaction as
//                 an empty item again without payload (i.e. without pbufs)
//
void NetworkTransaction::Defer(DeferralMode mode)
{
	if (mode == DeferralMode::ResetData)
	{
		// Reset the reading pointers and send an ACK
		inputPointer = 0;
		readingPb = pb;
		if (IsConnected() && pb != nullptr && !dataAcknowledged)
		{
			tcp_recved(cs->pcb, pb->tot_len);
			dataAcknowledged = true;
		}
	}
	else if (mode == DeferralMode::DiscardData)
	{
		// Discard the incoming data, because we don't need to process it any more
		FreePbuf();
	}

	status = deferred;

	// Unlink this transaction from the list of ready transactions and append it again
	Network& network = reprap.GetNetwork();
	NetworkTransaction *item, *previous = nullptr;
	for(item = network.readyTransactions; item != nullptr; item = item->next)
	{
		if (item == this)
		{
			if (previous == nullptr)
			{
				network.readyTransactions = next;
			}
			else
			{
				previous->next = next;
			}
			break;
		}
		previous = item;
	}
	network.AppendTransaction(&network.readyTransactions, this);

	// Append all other transactions that are associated to this connection, so that the
	// Webserver gets a chance to deal with all connected clients even while multiple
	// deferred requests are present in the list.
	item = network.readyTransactions;
	previous = nullptr;
	while (item != this)
	{
		if (item->cs == cs)
		{
			NetworkTransaction *nextItem = item->next;
			if (previous == nullptr)
			{
				network.readyTransactions = item->next;
				network.AppendTransaction(&network.readyTransactions, item);
			}
			else
			{
				previous->next = item->next;
				network.AppendTransaction(&network.readyTransactions, item);
			}
			item = nextItem;
		}
		else
		{
			previous = item;
			item = item->next;
		}
	}
}
Пример #5
0
// This is called by the Webserver to send output data to a client. If keepConnectionAlive is set to false,
// the current connection will be terminated once everything has been sent.
void NetworkTransaction::Commit(bool keepConnectionAlive)
{
	// If the connection has been terminated (e.g. RST received while writing upload data), discard this transaction
	if (!IsConnected() || status == released)
	{
		Discard();
		return;
	}

	// Free buffer holding the incoming data and prepare some values for the sending process
	FreePbuf();
	cs->persistConnection = keepConnectionAlive;
	if (sendBuffer == nullptr)
	{
		sendBuffer = sendStack->Pop();
	}
	status = sending;

	// Unlink the item(s) from the list of ready transactions
	if (keepConnectionAlive)
	{
		// Our connection is still of interest, remove only this transaction from the list
		NetworkTransaction *previous = nullptr;
		for(NetworkTransaction *item = reprap.GetNetwork().readyTransactions; item != nullptr; item = item->next)
		{
			if (item == this)
			{
				if (previous == nullptr)
				{
					reprap.GetNetwork().readyTransactions = next;
				}
				else
				{
					previous->next = next;
				}
				break;
			}
			previous = item;
		}
	}
	else
	{
		// We will close this connection soon, stop receiving data from this PCB
		tcp_recv(cs->pcb, nullptr);

		// Also remove all ready transactions pointing to our ConnectionState
		NetworkTransaction *previous = nullptr, *item = reprap.GetNetwork().readyTransactions;
		while (item != nullptr)
		{
			if (item->cs == cs)
			{
				if (item == this)
				{
					// Only unlink this item
					if (previous == nullptr)
					{
						reprap.GetNetwork().readyTransactions = next;
					}
					else
					{
						previous->next = next;
					}
					item = next;
				}
				else
				{
					// Remove all others
					item->Discard();
					item = (previous == nullptr) ? reprap.GetNetwork().readyTransactions : previous->next;
				}
			}
			else
			{
				previous = item;
				item = item->next;
			}
		}
	}

	// Enqueue this transaction, so it's sent in the right order
	NetworkTransaction *mySendingTransaction = cs->sendingTransaction;
	if (mySendingTransaction == nullptr)
	{
		cs->sendingTransaction = this;
		reprap.GetNetwork().AppendTransaction(&reprap.GetNetwork().writingTransactions, this);
	}
	else
	{
		while (mySendingTransaction->nextWrite != nullptr)
		{
			mySendingTransaction = mySendingTransaction->nextWrite;
		}
		mySendingTransaction->nextWrite = this;
	}
}