static void transfer_response(GObex *obex, GError *err, GObexPacket *rsp, gpointer user_data) { struct transfer *transfer = user_data; GObexPacket *req; gboolean rspcode, final; guint id; g_obex_debug(G_OBEX_DEBUG_TRANSFER, "transfer %u", transfer->id); id = transfer->req_id; transfer->req_id = 0; if (err != NULL) { transfer_complete(transfer, err); return; } rspcode = g_obex_packet_get_operation(rsp, &final); if (rspcode != G_OBEX_RSP_SUCCESS && rspcode != G_OBEX_RSP_CONTINUE) { err = g_error_new(G_OBEX_ERROR, rspcode, "%s", g_obex_strerror(rspcode)); goto failed; } if (transfer->opcode == G_OBEX_OP_GET) { handle_get_body(transfer, rsp, &err); if (err != NULL) goto failed; } if (rspcode == G_OBEX_RSP_SUCCESS) { transfer_complete(transfer, NULL); return; } if (transfer->opcode == G_OBEX_OP_PUT) { req = g_obex_packet_new(transfer->opcode, FALSE, G_OBEX_HDR_INVALID); g_obex_packet_add_body(req, put_get_data, transfer); } else if (!g_obex_srm_active(transfer->obex)) { req = g_obex_packet_new(transfer->opcode, TRUE, G_OBEX_HDR_INVALID); } else { /* Keep id since request still outstanting */ transfer->req_id = id; return; } transfer->req_id = g_obex_send_req(obex, req, -1, transfer_response, transfer, &err); failed: if (err != NULL) { g_obex_debug(G_OBEX_DEBUG_ERROR, "%s", err->message); transfer_complete(transfer, err); g_error_free(err); } }
static void transfer_response(GObex *obex, GError *err, GObexPacket *rsp, gpointer user_data) { struct transfer *transfer = user_data; GObexPacket *req; gboolean rspcode, final; transfer->req_id = 0; if (err != NULL) { transfer_complete(transfer, err); return; } rspcode = g_obex_packet_get_operation(rsp, &final); if (rspcode != G_OBEX_RSP_SUCCESS && rspcode != G_OBEX_RSP_CONTINUE) { err = g_error_new(G_OBEX_ERROR, rspcode, "Transfer failed (0x%02x)", rspcode); goto failed; } if (transfer->opcode == G_OBEX_OP_GET) { handle_get_body(transfer, rsp, &err); if (err != NULL) goto failed; } if (rspcode == G_OBEX_RSP_SUCCESS) { transfer_complete(transfer, NULL); return; } if (transfer->opcode == G_OBEX_OP_PUT) { req = g_obex_packet_new(transfer->opcode, FALSE, G_OBEX_HDR_INVALID); g_obex_packet_add_body(req, put_get_data, transfer); } else { req = g_obex_packet_new(transfer->opcode, TRUE, G_OBEX_HDR_INVALID); } transfer->req_id = g_obex_send_req(obex, req, -1, transfer_response, transfer, &err); failed: if (err != NULL) { transfer_complete(transfer, err); g_error_free(err); } }
static gssize put_get_data(void *buf, gsize len, gpointer user_data) { struct transfer *transfer = user_data; GObexPacket *req; GError *err = NULL; gssize ret; ret = transfer->data_producer(buf, len, transfer->user_data); if (ret >= 0) return ret; if (ret == -EAGAIN) return ret; req = g_obex_packet_new(G_OBEX_OP_ABORT, TRUE, G_OBEX_HDR_INVALID); transfer->req_id = g_obex_send_req(transfer->obex, req, -1, transfer_abort_response, transfer, &err); if (err != NULL) { transfer_complete(transfer, err); g_error_free(err); } return ret; }
static void transfer_abort_response(GObex *obex, GError *err, GObexPacket *rsp, gpointer user_data) { struct transfer *transfer = user_data; transfer->req_id = 0; /* Intentionally override error */ err = g_error_new(G_OBEX_ERROR, G_OBEX_ERROR_CANCELLED, "Operation was aborted"); transfer_complete(transfer, err); g_error_free(err); }
static void transfer_abort_req(GObex *obex, GObexPacket *req, gpointer user_data) { struct transfer *transfer = user_data; GObexPacket *rsp; GError *err; err = g_error_new(G_OBEX_ERROR, G_OBEX_ERROR_CANCELLED, "Request was aborted"); rsp = g_obex_packet_new(G_OBEX_RSP_SUCCESS, TRUE, G_OBEX_HDR_INVALID); g_obex_send(obex, rsp, NULL); transfer_complete(transfer, err); g_error_free(err); }
static void transfer_abort_response(GObex *obex, GError *err, GObexPacket *rsp, gpointer user_data) { struct transfer *transfer = user_data; g_obex_debug(G_OBEX_DEBUG_TRANSFER, "transfer %u", transfer->id); transfer->req_id = 0; /* Intentionally override error */ err = g_error_new(G_OBEX_ERROR, G_OBEX_ERROR_CANCELLED, "Operation was aborted"); g_obex_debug(G_OBEX_DEBUG_ERROR, "%s", err->message); transfer_complete(transfer, err); g_error_free(err); }
static gssize put_get_data(void *buf, gsize len, gpointer user_data) { struct transfer *transfer = user_data; GObexPacket *req; GError *err = NULL; gssize ret; ret = transfer->data_producer(buf, len, transfer->user_data); if (ret == 0 || ret == -EAGAIN) return ret; if (ret > 0) { /* Check if SRM is active */ if (!g_obex_srm_active(transfer->obex)) return ret; /* Generate next packet */ req = g_obex_packet_new(transfer->opcode, FALSE, G_OBEX_HDR_INVALID); g_obex_packet_add_body(req, put_get_data, transfer); transfer->req_id = g_obex_send_req(transfer->obex, req, -1, transfer_response, transfer, &err); goto done; } req = g_obex_packet_new(G_OBEX_OP_ABORT, TRUE, G_OBEX_HDR_INVALID); transfer->req_id = g_obex_send_req(transfer->obex, req, -1, transfer_abort_response, transfer, &err); done: if (err != NULL) { transfer_complete(transfer, err); g_error_free(err); } return ret; }
/* USB_TRCPT1_0, USB_TRCPT1_1, USB_TRCPT1_2, USB_TRCPT1_3, USB_TRCPT1_4, USB_TRCPT1_5, USB_TRCPT1_6, USB_TRCPT1_7 */ void USB_3_Handler(void) { transfer_complete(TUSB_DIR_IN); }
/* USB_TRCPT0_0, USB_TRCPT0_1, USB_TRCPT0_2, USB_TRCPT0_3, USB_TRCPT0_4, USB_TRCPT0_5, USB_TRCPT0_6, USB_TRCPT0_7 */ void USB_2_Handler(void) { transfer_complete(TUSB_DIR_OUT); }
void MegaFuseApp::transfer_update(int td, m_off_t bytes, m_off_t size, dstime starttime) { std::string remotename = ""; if(model->cacheManager.findByTransfer(td,file_cache_row::UPLOADING ) != model->cacheManager.end()) { printf("\033[2KUPLOAD TD %d: Update: %lld KB of %lld KB, %0.2f KB/s\r", td, bytes/1024, size/1024, float(1.0*bytes*10/(1024*(client->httpio->ds-starttime)+1))); fflush(stdout); return; } auto it = model->cacheManager.findByTransfer(td,file_cache_row::DOWNLOADING ); if(it == model->cacheManager.end()) { //no file found client->tclose(td); return; } int startChunk = CacheManager::numChunks(it->second.startOffset); it->second.available_bytes = ChunkedHash::chunkfloor(ChunkedHash::chunkfloor(it->second.startOffset) + bytes); int endChunk = CacheManager::numChunks(ChunkedHash::chunkfloor(it->second.available_bytes)); if(it->second.startOffset + bytes >= size) { it->second.available_bytes = size; endChunk = it->second.availableChunks.size(); } for(int i = startChunk; i < endChunk; i++) { try { if(!it->second.availableChunks[i]) { it->second.availableChunks[i] = true; } } catch(...) { printf("\033[2KError while reading block %d\n", i); fflush(stdout); abort(); } } { std::string r; size_t n = it->second.availableChunks.size(); for(size_t i=0; i<n; ++i) r.append(it->second.availableChunks[i]?"#":"-"); std::string t; unsigned char c; while(r.length() > 60) { t = ""; n = r.length(); for(size_t i=0; i<n; i += 3) { c = 0; for(unsigned short z=0; z<3; ++z) if(i+z >= n || r.at(i+z) == '#') c++; t.append(c>1?"#":"-"); } r = t; } //static time_t last_update = time(NULL); //if(last_update < time(NULL)) //{ printf("\033[2K[%s] %0.2f/%0.2f MB, %lld KB/s\r", r.c_str(), float(1.0*(it->second.startOffset+bytes)/1024/1024), float(1.0*size/1024/1024), 10*bytes/(1024*(client->httpio->ds-starttime)+1)); fflush(stdout); // last_update = time(NULL); //} } model->eh.notifyEvent(EventsHandler::TRANSFER_UPDATE,0); if(it->second.n_clients <= 0) { client->tclose(it->second.td); it->second.status =file_cache_row::DOWNLOAD_PAUSED; it->second.td = -1; printf("\033[2KDownload paused\n"); } //WORKAROUNDS if(it->second.startOffset && it->second.available_bytes>= it->second.size) { // Workaround #1 - have to call manually if the download didn't start at 0 transfer_complete(td, NULL, NULL); } else if(endChunk > startChunk && endChunk < it->second.availableChunks.size() && it->second.availableChunks[endChunk]) { printf("\033[2KEncountered already available data at block %d. Stopping...\n", endChunk); transfer_complete(td, NULL, NULL); } }
void MegaFuseApp::transfer_update(int td, m_off_t bytes, m_off_t size, dstime starttime) { std::string remotename = ""; if(model->cacheManager.findByTransfer(td,file_cache_row::UPLOADING ) != model->cacheManager.end()) { cout << '\r'<<"UPLOAD TD " << td << ": Update: " << bytes/1024 << " KB of " << size/1024 << " KB, " << bytes*10/(1024*(client->httpio->ds-starttime)+1) << " KB/s" ; fflush(stdout); return; } auto it = model->cacheManager.findByTransfer(td,file_cache_row::DOWNLOADING ); if(it == model->cacheManager.end()) { //no file found client->tclose(td); return; } int startChunk = CacheManager::numChunks(it->second.startOffset); it->second.available_bytes = ChunkedHash::chunkfloor(ChunkedHash::chunkfloor(it->second.startOffset) + bytes); int endChunk = CacheManager::numChunks(ChunkedHash::chunkfloor(it->second.available_bytes)); if(it->second.startOffset + bytes >= size) { it->second.available_bytes = size; endChunk = it->second.availableChunks.size(); } for(int i = startChunk; i < endChunk; i++) { try { if(!it->second.availableChunks[i]) { it->second.availableChunks[i] = true; printf("block %d/%d available\n",i,(int)it->second.availableChunks.size()); } } catch(...) { printf("errore, ho provato a leggere il blocco %d\n",i); fflush(stdout); abort(); } } /* cout << remotename << td << ": Update: " << bytes/1024 << " KB of " << size/1024 << " KB, " << bytes*10/(1024*(client->httpio->ds-starttime)+1) << " KB/s" << endl; cout << "scaricato fino al byte " <<(it->second.startOffset+bytes) << " di: "<<size<<endl; */ { std::string rigaDownload = "\r["; int numero = it->second.availableChunks.size(); for(int i = 0;i<50;i++) { if(it->second.availableChunks[i*numero/50]) rigaDownload.append("#"); else rigaDownload.append("-"); } rigaDownload.append("] "); //std::cout << "readable bytes: " << ChunkedHash::chunkfloor(ChunkedHash::chunkfloor(it->second.startOffset) + bytes) <<std::endl; static time_t last_update= time(NULL); if(last_update < time(NULL)) { std::cout << rigaDownload << size/1024/1024 << " MB, " << bytes*10/(1024*(client->httpio->ds-starttime)+1) << " KB/s, available_b/size " <<it->second.available_bytes<<"/"<<it->second.size<< " "<<(it->second.startOffset+bytes)<< "/" <<size<<" "; last_update = time(NULL); } } model->eh.notifyEvent(EventsHandler::TRANSFER_UPDATE,0); if( it->second.n_clients<=0) { client->tclose(it->second.td); it->second.status =file_cache_row::DOWNLOAD_PAUSED; it->second.td = -1; printf("pausing download\n"); } //WORKAROUNDS if(it->second.startOffset && it->second.available_bytes>= it->second.size) { printf("workaround 1\n"); //have to call manually if the download didn't start at 0 transfer_complete(td,NULL,NULL); } else if(endChunk > startChunk && endChunk < it->second.availableChunks.size() && it->second.availableChunks[endChunk]) { printf("----Downloading already available data at block %d. stopping...\n",endChunk); transfer_complete(td,NULL,NULL); } }