void Network::Spin() { if (active) { // ++inLwip; ethernet_task(); // keep the Ethernet running // --inLwip; // See if we can send anything RequestState* r = writingTransactions; if (r != NULL) { bool finished = r->Send(); // Disable interrupts while we mess around with the lists in case we get a callback from a network ISR irqflags_t flags = cpu_irq_save(); writingTransactions = r->next; if (finished) { RequestState *rn = r->nextWrite; r->nextWrite = NULL; HttpState *hs = r->hs; AppendTransaction(&freeTransactions, r); if (rn != NULL) { if (hs != NULL) { hs->sendingRs = (rn->hs == hs) ? rn : NULL; } AppendTransaction(&writingTransactions, rn); } else if (hs != NULL) { hs->sendingRs = NULL; } } else { AppendTransaction(&writingTransactions, r); } cpu_irq_restore(flags); } } else if (establish_ethernet_link()) { start_ethernet(reprap.GetPlatform()->IPAddress(), reprap.GetPlatform()->NetMask(), reprap.GetPlatform()->GateWay()); httpd_init(); active = true; } }
// We have no data to write and we want to keep the current connection alive if possible. // That way we can speed up freeing the current NetworkTransaction. void Network::CloseTransaction() { // Free the current NetworkTransaction's data (if any) NetworkTransaction *r = readyTransactions; if (r == NULL) { return; } r->FreePbuf(); // Terminate this connection if this NetworkTransaction indicates a graceful disconnect TransactionStatus status = r->status; if (!r->LostConnection() && status == disconnected) { // debugPrintf("Network: CloseRequest is closing connection cs=%08x\n", (unsigned int)locCs); ConnectionClosed(r->cs, true); } // Remove the current item from readyTransactions readyTransactions = r->next; // Append it to freeTransactions again unless it's already on another list if (status != dataSending) { AppendTransaction(&freeTransactions, r); } }
// This is called when a connection is being established and returns an initialised ConnectionState instance. ConnectionState *Network::ConnectionAccepted(tcp_pcb *pcb) { ConnectionState *cs = freeConnections; if (cs == NULL) { platform->Message(HOST_MESSAGE, "Network::ConnectionAccepted() - no free ConnectionStates!\n"); return NULL; } NetworkTransaction* r = freeTransactions; if (r == NULL) { platform->Message(HOST_MESSAGE, "Network::ConnectionAccepted() - no free transactions!\n"); return NULL; } freeConnections = cs->next; cs->Init(pcb); r->Set(NULL, cs, connected); freeTransactions = r->next; AppendTransaction(&readyTransactions, r); return cs; }
// Send the output data we already have, optionally with a file appended, then close the connection unless keepConnectionOpen is true. // The file may be too large for our buffer, so we may have to send it in multiple transactions. void Network::SendAndClose(FileStore *f, bool keepConnectionOpen) { irqflags_t flags = cpu_irq_save(); RequestState *r = readyTransactions; if (r == NULL) { cpu_irq_restore(flags); } else { readyTransactions = r->next; cpu_irq_restore(flags); r->FreePbuf(); if (r->LostConnection()) { if (f != NULL) { f->Close(); } AppendTransaction(&freeTransactions, r); // debugPrintf("Conn lost before send\n"); } else { r->nextWrite = NULL; r->fileBeingSent = f; r->persistConnection = keepConnectionOpen; RequestState *sendingRs = r->hs->sendingRs; if (sendingRs == NULL) { r->hs->sendingRs = r; AppendTransaction(&writingTransactions, r); //debug // r->outputBuffer[r->outputPointer] = 0; // debugPrintf("Transaction queued for writing to network, file=%c, data=%s\n", (f ? 'Y' : 'N'), r->outputBuffer); } else { while (sendingRs->nextWrite != NULL) { sendingRs = sendingRs->nextWrite; } sendingRs->nextWrite = r; } } } }
void Network::ConnectionClosedGracefully(ConnectionState *cs) { NetworkTransaction* r = freeTransactions; if (r == NULL) { platform->Message(HOST_MESSAGE, "Network::ConnectionClosedGracefully() - no free transactions!\n"); return; } freeTransactions = r->next; r->Set(NULL, cs, disconnected); AppendTransaction(&readyTransactions, r); }
void Network::ReceiveInput(pbuf *pb, ConnectionState* cs) { NetworkTransaction* r = freeTransactions; if (r == NULL) { platform->Message(HOST_MESSAGE, "Network::ReceiveInput() - no free transactions!\n"); return; } freeTransactions = r->next; r->Set(pb, cs, dataReceiving); AppendTransaction(&readyTransactions, r); // debugPrintf("Network - input received\n"); }
void Network::ReceiveInput(pbuf *pb, HttpState* hs) { irqflags_t flags = cpu_irq_save(); RequestState* r = freeTransactions; if (r == NULL) { cpu_irq_restore(flags); reprap.GetPlatform()->Message(HOST_MESSAGE, "Network::ReceiveInput() - no free transactions!\n"); return; } freeTransactions = r->next; cpu_irq_restore(flags); r->Set(pb, hs); AppendTransaction(&readyTransactions, r); // debugPrintf("Network - input received\n"); }
// Send the output data we already have, optionally with a file appended, then close the connection unless keepConnectionOpen is true. // The file may be too large for our buffer, so we may have to send it in multiple transactions. void Network::SendAndClose(FileStore *f, bool keepConnectionOpen) { NetworkTransaction *r = readyTransactions; if (r == NULL) { return; } if (r->status == dataSending) { // This transaction is already in use for sending (e.g. a Telnet request), // so all we have to do is to remove it from readyTransactions. readyTransactions = r->next; } else { readyTransactions = r->next; if (r->LostConnection()) { if (f != NULL) { f->Close(); } while (r->sendBuffer != NULL) { r->sendBuffer = ReleaseSendBuffer(r->sendBuffer); } AppendTransaction(&freeTransactions, r); // debugPrintf("Conn lost before send\n"); } else { r->FreePbuf(); r->cs->persistConnection = keepConnectionOpen; r->fileBeingSent = f; r->status = dataSending; if (f != NULL && r->sendBuffer == NULL) { SendBuffer *buf; if (AllocateSendBuffer(buf)) { r->sendBuffer = buf; r->fileBeingSent = f; } else { r->fileBeingSent = NULL; // debugPrintf("Could not allocate send buffer for file transfer!\n"); } } NetworkTransaction *mySendingTransaction = r->cs->sendingTransaction; if (mySendingTransaction == NULL) { r->cs->sendingTransaction = r; AppendTransaction(&writingTransactions, r); //debug // r->outputBuffer[r->outputPointer] = 0; // debugPrintf("Transaction queued for writing to network, file=%c, data=%s\n", (f ? 'Y' : 'N'), r->outputBuffer); } else { while (mySendingTransaction->nextWrite != NULL) { mySendingTransaction = mySendingTransaction->nextWrite; } mySendingTransaction->nextWrite = r; // debugPrintf("Transaction appended to sending RS\n"); } } } }
void Network::Spin() { // Basically we can't do anything if we can't interact with LWIP if (!LockLWIP()) { platform->ClassReport(longWait); return; } if (state == NetworkActive) { // See if we can read any packets if (readingData) { readingData = false; do { // read all queued packets from the RX buffer } while (ethernet_read()); ethernet_set_rx_callback(&emac_read_packet); } // See if we can send anything NetworkTransaction *r = writingTransactions; if (r != NULL && r->Send()) { // We're done, free up this transaction ConnectionState *cs = r->cs; NetworkTransaction *rn = r->nextWrite; writingTransactions = r->next; AppendTransaction(&freeTransactions, r); // If there is more data to write on this connection, do it next time if (cs != NULL) { cs->sendingTransaction = rn; } if (rn != NULL) { PrependTransaction(&writingTransactions, rn); } } } else if (state == NetworkInitializing && establish_ethernet_link()) { start_ethernet(platform->IPAddress(), platform->NetMask(), platform->GateWay()); ethernet_set_rx_callback(&emac_read_packet); httpd_init(); ftpd_init(); telnetd_init(); netbios_init(); state = NetworkActive; } UnlockLWIP(); platform->ClassReport(longWait); }