Adds file transfer capability to SimpleSerialProtocol
Dependents: SerialFileReceiver
Diff: SerialFileTransfer.cpp
- Revision:
- 0:31dff1f79b4f
- Child:
- 1:f8aaff9c57e3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SerialFileTransfer.cpp Wed Aug 27 17:59:05 2014 +0000 @@ -0,0 +1,106 @@ +#include "SerialFileTransfer.h" + +extern Serial debug; + +LocalFileSystem local("local"); + +void SFTProtocol::update(SimpleSerialProtocol::Protocol* comms){ + if(last_chunk_timer.read_ms() > 100 && transfer_in_progress){ + last_chunk_timer.reset(); + packet_retry_attempts++; + if(packet_retry_attempts > 50){ + ack(comms, 3); + //debug.printf("Transfer Timeout\r\n"); + packet_retry_attempts = 0; + transfer_in_progress = false; + chunks_last = 0; + chunks_total = 0; + fclose(fp); + fp = 0; + last_chunk_timer.stop(); + last_chunk_timer.reset(); + } else { + //debug.printf("Request Packet Resend %d, %d\r\n", comms->droppedBytes(), comms->_corrupt_packets); + ack(comms, 2); + } + } +} + +void SFTProtocol::onFileStart(SimpleSerialProtocol::Protocol* comms, SimpleSerialProtocol::Packet* packet){ + if(!packet)return; + if (packet->_valid) { + FileStartPacket::Interface* interface = packet->interpretData<FileStartPacket::Interface>(); + if (interface) { + //debug.printf("%s.%s has %d chunks\r\n", interface->name, interface->ext, interface->chunks); + + char buffer[25]; + sprintf(buffer, "/local/%s.%s", interface->name, interface->ext); + fp = fopen(buffer, "w"); + if(fp){ + transfer_in_progress = true; + chunks_total = interface->chunks; + ack(comms, 0); + last_chunk_timer.start(); + } + } + } + return; +} + +void SFTProtocol::onFileStream(SimpleSerialProtocol::Protocol* comms, SimpleSerialProtocol::Packet* packet){ + if(!packet)return; + if(transfer_in_progress){ + if (packet->_valid) { + FileStreamPacket::Interface* interface = packet->interpretData<FileStreamPacket::Interface>(); + if (interface) { + //debug.printf("%d,%d\r\n", interface->chunk, interface->length); + //if(rand()%5 < 1){ //1in5 packet loss emulation + if((interface->chunk <= chunks_last + 1) && fp ){ + + if(interface->chunk == chunks_last + 1){ + chunks_last = interface->chunk; + fwrite(interface->data, 1, interface->length, fp); + } else { + //debug.printf("Allready have chunk %d\r\n", interface->chunk); + } + + if(chunks_last == chunks_total){ + //debug.printf("Transfer Complete: Acked\r\n"); + ack(comms, 1); + fclose(fp); + fp = 0; + transfer_in_progress = false; + chunks_last = 0; + chunks_total = 0; + last_chunk_timer.stop(); + last_chunk_timer.reset(); + }else{ + ack(comms, 0); + packet_retry_attempts = 0; + last_chunk_timer.reset(); + } + + } else { + //debug.printf("Transfer Failed: chunk dropped or out of order\r\n"); + transfer_in_progress = false; + chunks_last = 0; + chunks_total = 0; + fclose(fp); + fp = 0; + ack(comms, 3); + last_chunk_timer.stop(); + last_chunk_timer.reset(); + } + } + //} + } + } + return; +} + +void SFTProtocol::ack(SimpleSerialProtocol::Protocol* comms, uint8_t ack_type) { + AckFileStartPacket message; + message.interface.ack_type = ack_type; + message.buildData<AckFileStartPacket::Interface>(&message.interface); + comms->sendPacket(&message); +} \ No newline at end of file