/* $Id: frecv.c,v 1.2 2003/10/27 09:55:46 roca Exp $ */ /* * Copyright (c) 1999-2003 INRIA - Universite Paris 6 - All rights reserved * (main authors: Julien Laboure - julien.laboure@inrialpes.fr * Vincent Roca - vincent.roca@inrialpes.fr) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ /* * frecv.c * * fcast receiver side functions */ #include "fcast.h" void FcastRecv(void) { int Bytes_received = 0; // int received = 0; int mcl_option; #if defined(ALC) if (optimode == OPTIMIZE_SPACE) { mcl_option = 1; if (mcl_ctl(id, MCL_OPT_IMMEDIATE_DELIVERY, (void*)&mcl_option, sizeof(mcl_option))) EXIT(("mcl_ctl: MCL_OPT_IMMEDIATE_DELIVERY failed\n")) mcl_option = 0; if (mcl_ctl(id, MCL_OPT_POSTPONE_FEC_DECODING, (void*)&mcl_option, sizeof(mcl_option))) { /* non critical... ignore! */ //EXIT(("mcl_ctl: MCL_OPT_POSTPONE_FEC_DECODING failed\n")) } } else if (optimode == OPTIMIZE_SPEED) { mcl_option = 1; if (mcl_ctl(id, MCL_OPT_IMMEDIATE_DELIVERY, (void*)&mcl_option, sizeof(mcl_option))) EXIT(("mcl_ctl: MCL_OPT_IMMEDIATE_DELIVERY failed\n")) mcl_option = 0; if (mcl_ctl(id, MCL_OPT_POSTPONE_FEC_DECODING, (void*)&mcl_option, sizeof(mcl_option))) { /* non critical... ignore! */ //EXIT(("mcl_ctl: MCL_OPT_POSTPONE_FEC_DECODING failed\n")) } } else if (optimode == OPTIMIZE_CPU) { mcl_option = 0; if (mcl_ctl(id, MCL_OPT_IMMEDIATE_DELIVERY, (void*)&mcl_option, sizeof(mcl_option))) EXIT(("mcl_ctl: MCL_OPT_IMMEDIATE_DELIVERY failed\n")) mcl_option = 1; if (mcl_ctl(id, MCL_OPT_POSTPONE_FEC_DECODING, (void*)&mcl_option, sizeof(mcl_option))) { /* * non critical... ignore! * for instance, this is only valid if RSE is used, * but does not apply to LDPC/LDGM */ //EXIT(("mcl_ctl: MCL_OPT_POSTPONE_FEC_DECODING failed\n")) } } else { EXIT(("FATAL ERROR: invalid optimization mode!")) } #endif /* RM_PROTOCOL */ if (src_addr > 0) /* in host format! */ { if (mcl_ctl(id, MCL_OPT_SRC_ADDR, (void*)&src_addr, sizeof(src_addr))) EXIT(("mcl_ctl: MCL_OPT_SRC_ADDR failed\n")) } PRINT(("Waiting for data...\n")) // while( (received = RecvOneFile()) >= 0 ) // Bytes_received += received; Bytes_received = RecvFiles(); mcl_close(id); PRINT(("\nFcastRecv completed, %d bytes received\n", Bytes_received)) } int RecvFiles(void) { char *buf_file = NULL; /* buffer for recv'd fragment */ unsigned char BlockTmp4[4]; char file_path[MAX_FILENAME + MAX_PATH]; int len = 0; char *Trailer = NULL; unsigned short global_sum = 0; unsigned long trailerlength = 0; meta_t *MetaList = NULL; meta_t *lpMetaData = NULL; int CurrFrag = 0; int offset = 0; int received = 0; long FragLength = 0; pFFile PartialFiles = NULL; pFFile ThisFile; int max_fragment_size; /* Big files are fragmented into fragments of this size */ /* determine the maximum fragment size (pessimistic evaluation that * does not take FEC used into account) */ max_fragment_size = RSE_MAX_FRAGMENT_SIZE; #ifdef ALC max_fragment_size = max(max_fragment_size, LDPC_MAX_FRAGMENT_SIZE); #endif /* RM_PROTOCOL */ max_fragment_size = max(max_fragment_size, NO_FEC_MAX_FRAGMENT_SIZE); /* Objects contain a file (or fragment), with its associated trailer * and checksum... */ if(!(buf_file = (char*)malloc(max_fragment_size + MAX_TRAILER_SIZE))) { EXIT(("Error: Cannot alloc memory!\n")) } /* Receiving ALL Object... */ while((len = mcl_recv(id, buf_file, max_fragment_size + MAX_TRAILER_SIZE)) != -1) { #ifdef DEBUG PRINT(("New Object Received (%d Bytes)\n", len)) #endif #if 0 /* Realloc the Buffer to fit our needs */ if (!(buf_file = (char*)realloc(buf_file, len))) { EXIT(("Error: Cannot realloc memory (RecvFiles)!\n")) } #endif /* Compute the Checksum and check if GlobalSum is 0xFFFF (checksum == 0) */ global_sum = ComputeSum( (unsigned short*)buf_file, len, NULL ); if ( global_sum != 0xFFFF) { EXIT(("Fcast ERROR: Invalid Checksum!!! (sum 0x%X)\n", global_sum)) } /* Get the Trailer Infos */ memcpy( BlockTmp4, (buf_file+len-8), 4); trailerlength = BUFFER_TO_INT32(BlockTmp4); #ifdef DEBUG PRINT(("\n)=> Trailer infos: %ld Bytes.\n", trailerlength)) #endif if (!(Trailer = (char*)malloc(trailerlength + 1))) { EXIT(("Error: Cannot alloc memory!\n")) } memcpy( Trailer, (buf_file +len -8 -trailerlength), trailerlength ); Trailer[trailerlength]= '\0'; /* Parse All Metas from the Trailer */ MetaList = ParseTrailer(Trailer); free(Trailer); GetFilePathFromMeta(MetaList, file_path); if( (FragLength = GetMetaLength(MetaList)) != (long)(len -8 -trailerlength) ) { EXIT(("Fcast ERROR: Size of fragment received and \"Content-length\" value don't match! (%ld!=%ld)\n",lpMetaData->value, GetMetaLength(MetaList))) } FFilePrintList(PartialFiles); ThisFile = FFileFind(file_path, PartialFiles); if(ThisFile == NULL) /* First fragment for this FILE */ { FFile NewFile; strncpy(NewFile.fullname, file_path, MAX_PATH+MAX_FILENAME ); #ifdef DEBUG PRINT(("New File received: %s\n", NewFile.fullname)) #endif PrintMetaList(MetaList); NewFile.writeIt = CheckWriteContext(NewFile.fullname, overwrite); if(NewFile.writeIt) { #ifdef WIN32 if ((NewFile.fd = open( NewFile.fullname, O_WRONLY | O_CREAT | O_BINARY | O_TRUNC, _S_IWRITE) ) < 0) #else if ((NewFile.fd = open( NewFile.fullname, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU)) < 0) #endif { EXIT(("Error while opening file \"%s\"\n", NewFile.fullname)) } } NewFile.filesize = GetMetaFilesize(MetaList); NewFile.nbFragRcvd = 1; NewFile.next = NULL; GetMetaFragment(MetaList, &CurrFrag, &NewFile.nbFragTot); FFileInsert(&PartialFiles, NewFile); ThisFile = FFileFind(file_path, PartialFiles); } else /* We've already received fragment(s) from this file */ { int nbfrag; ASSERT(!strcmp(ThisFile->fullname, file_path)) #ifdef DEBUG PRINT(("File %s already in database...\n", ThisFile->fullname)) #endif /* ASSERT(ThisFile->fd != 0) */ ASSERT(ThisFile->filesize == GetMetaFilesize(MetaList)) ASSERT(ThisFile->nbFragRcvd >0 ) GetMetaFragment(MetaList, &CurrFrag, &nbfrag); ASSERT(ThisFile->nbFragTot == nbfrag) ThisFile->nbFragRcvd++; } ASSERT(ThisFile != NULL) ASSERT(ThisFile->nbFragRcvd<= ThisFile->nbFragTot) if(ThisFile->writeIt) { PRINT(("Processing fragment %d of file %s (Total=%d / Rcvd=%d)\n", CurrFrag, ThisFile->fullname, ThisFile->nbFragTot, ThisFile->nbFragRcvd)) offset = GetMetaOffset(MetaList); #ifdef DEBUG PRINT(("\tWriting %ld bytes at offset %d\n", FragLength, offset)) #endif if (lseek((int)ThisFile->fd, (long)offset, SEEK_SET) < 0) EXIT(("Error: lseek failed\n")) if (write((int)ThisFile->fd, buf_file, FragLength) < 0) EXIT(("mclrecv: write failed\n")) if(ThisFile->nbFragRcvd == ThisFile->nbFragTot) // This File is complete! { PRINT(("Finished receiving file \"%s\" (%ld Bytes).\n", ThisFile->fullname, ThisFile->filesize)) ASSERT(ThisFile->fd != 0) close(ThisFile->fd); FFileRemove(ThisFile->fullname, &PartialFiles); } received += len; } else /* This is a skipped file */ { PRINT(("Skipping fragment %d of file %s (Total=%d / Rcvd=%d) (file already exists)\n", CurrFrag, ThisFile->fullname, ThisFile->nbFragTot, ThisFile->nbFragRcvd)) if(ThisFile->nbFragRcvd == ThisFile->nbFragTot) // This File is complete! { PRINT(("File \"%s\" -> All fragments have been skipped (file already exists).\n", ThisFile->fullname)) //ASSERT(ThisFile->fd == 0) FFileRemove(ThisFile->fullname, &PartialFiles); } } DestroyMetalist(MetaList); #if 0 if (!(buf_file = (char*)realloc(buf_file, max_fragment_size + MAX_TRAILER_SIZE))) { EXIT(("Error: Cannot realloc memory (RecvFiles)!\n")) } #endif } if (PartialFiles != NULL) // When loop ends, all files must be completed! { FFilePrintList(PartialFiles); EXIT(("Fcast ERROR: MCL session closed and there are missing fragments\n")) // TODO display missing files/fragment } if(buf_file) free(buf_file); return received; } //int RecvOneFile(void) //{ // char *buf_file = NULL; // unsigned char BlockTmp4[4]; // // char file_base[MAX_PATH]; // char file_name[MAX_FILENAME]; // char file_path[MAX_FILENAME + MAX_PATH]; // int len = 0; // char *Trailer = NULL; // unsigned short global_sum = 0; // unsigned long trailerlength = 0; // unsigned long FragLength = 0; // unsigned int writeIt = 0; // int saved_file = 0; // meta_t *MetaList = NULL; // meta_t *lpMetaData = NULL; // // // int IndFrag = 0; // int CurrFrag = 0; // int TotFrag = 0; // int offset = 0; // int received = 0; // int FileLength = 0; // // // /* Receive a file_slice, with its associated trailer, and checksum... */ // if(!(buf_file = (char*)malloc(MAX_FRAGMENT_SIZE + MAX_TRAILER_SIZE))) { // EXIT(("Error: Cannot alloc memory!\n")) // } // // len = mcl_recv(id, buf_file, MAX_FRAGMENT_SIZE + MAX_TRAILER_SIZE); // if ( len < 0 ) // { // received = -1; // goto end; // } // PRINT(("New Object Received (%d Bytes)\n", len)) // // if (!(buf_file = (char*)realloc(buf_file, len))) { // EXIT(("Error: Cannot realloc memory (RecvOneFile)!\n")) // } // // global_sum = ComputeSum( (unsigned short*)buf_file, len, NULL ); // // /* Global Sum must be all 1s (checksum == 0) */ // if ( global_sum != 0xFFFF) // { // EXIT(("Invalid Checksum!!! (sum 0x%X)\n", global_sum)) // } // // memcpy( BlockTmp4, (buf_file+len-8), 4); // trailerlength = BUFFER_TO_INT32(BlockTmp4); // PRINT(("\n)=> New file... trailer infos: %ld Bytes.\n", trailerlength)) // // if (!(Trailer = (char*)malloc(trailerlength + 1))) { // EXIT(("Error: Cannot alloc memory!\n")) // } // memcpy( Trailer, (buf_file +len -8 -trailerlength), trailerlength ); // Trailer[trailerlength]= '\0'; // // MetaList = ParseTrailer(Trailer); // free(Trailer); // lpMetaData = MetaList; // while(lpMetaData != NULL) // { // PRINT(("\t%s: %s\n", lpMetaData->name, lpMetaData->content)) // lpMetaData = lpMetaData->next; // } // // lpMetaData = FindMeta(MetaList, "Content-Location"); // if(lpMetaData == NULL) // { // PRINT(("Meta Content-location unavailable, file name is unknown, can't save...\n")) // } // else { // strncpy(file_name, lpMetaData->content, MAX_FILENAME); // if((lpMetaData = FindMeta(MetaList, "Content-Base"))!=NULL) // strncpy(file_base, lpMetaData->content, MAX_PATH); // else // strcpy(file_base, "./"); // strncpy(file_path, file_base, MAX_PATH); // strcat(file_path, file_name); // writeIt = CheckWriteContext(file_path, overwrite); // } // // FragLength = len -8 -trailerlength; // // if((lpMetaData = FindMeta(MetaList, "Content-Length"))!=NULL) // { // if( lpMetaData->value != (long)FragLength ) // PRINT(("Warning: Size of fragment received and \"Content-length\" value doesn't match! (%ld!=%ld)\n",lpMetaData->value, FragLength)) // } // if((lpMetaData = FindMeta(MetaList, "Content-Filesize"))!=NULL) // { // FileLength = lpMetaData->value; // } // else // { // EXIT(("Error: Missing Meta Content-Filesize")) // } // // if(writeIt) // { // #ifdef WIN32 // if ((saved_file = open( file_path, O_WRONLY | O_CREAT | O_BINARY, _S_IWRITE) ) < 0) // #else // if ((saved_file = open( file_path, O_WRONLY | O_CREAT, S_IRWXU)) < 0) // #endif // { // perror("Error : "); // EXIT(("Error while opening file \"%s\"\n", file_path)) // } // // lpMetaData = FindMeta(MetaList, "Content-Fragment"); // if(lpMetaData == NULL) // { // EXIT(("Error: Meta Content-Fragment unavailable\n")) // } // else // { char *token; // token = strtok( lpMetaData->content, "/" ); // if( token != NULL ) // { // CurrFrag = atoi(token); // token = strtok( NULL, "/" ); // if( token != NULL ) // TotFrag = atoi(token); // else // EXIT(("Error: Invalide Meta (Content-Fragment)\n")) // } // else // EXIT(("Error: Invalide Meta (Content-Fragment)\n")) // // PRINT(("Processing fragment %d of file %s (%d fragments)\n", CurrFrag, file_path, TotFrag)) // lpMetaData = FindMeta(MetaList, "Content-Offset"); // if(lpMetaData == NULL) // { // EXIT(("Error: Meta Content-Offset unavailable\n")) // } // else // { // offset = lpMetaData->value; // PRINT(("\tWriting %ld bytes at offset %d\n", FragLength, offset)) // // if (lseek((int)saved_file, (long)offset, SEEK_SET) < 0) // EXIT(("Error: lseek failed\n")) // if (write((int)saved_file, buf_file, FragLength) < 0) // EXIT(("mclrecv: write failed\n")) // received += len; // // } // DestroyMetalist(MetaList); // IndFrag = 1; // // while(IndFrag < TotFrag) // { // /* Receive next file_slice, with its associated trailer, and checksum... */ // if(!(buf_file = (char*)realloc(buf_file, MAX_FRAGMENT_SIZE + MAX_TRAILER_SIZE))) { // EXIT(("Error: Cannot alloc memory!\n")) // } // // if ((len = mcl_recv(id, buf_file, MAX_FRAGMENT_SIZE + MAX_TRAILER_SIZE)) < 0 ) // { // EXIT(("Error: mcl_recv failed while there were missing fragments\n")) // } // PRINT(("New Object Received (%d Bytes)\n", len)) // // if (!(buf_file = (char*)realloc(buf_file, len))) { // EXIT(("Error: Cannot realloc memory!\n")) // } // // global_sum = ComputeSum( (unsigned short*)buf_file, len, NULL ); // /* Global Sum must be all 1s (checksum == 0) */ // if ( global_sum != 0xFFFF) // { // EXIT(("Invalid Checksum!!! (sum 0x%X)\n", global_sum)) // } // // memcpy( BlockTmp4, (buf_file+len-8), 4); // trailerlength = BUFFER_TO_INT32(BlockTmp4); // PRINT(("\n)=> New FileSLICE received... trailer infos: %ld Bytes.\n", trailerlength)) // // if (!(Trailer = (char*)malloc(trailerlength + 1))) { // EXIT(("Error: Cannot alloc memory!\n")) // } // memcpy( Trailer, (buf_file +len -8 -trailerlength), trailerlength ); // Trailer[trailerlength]= '\0'; // // MetaList = ParseTrailer(Trailer); // free(Trailer); // lpMetaData = MetaList; // while(lpMetaData != NULL) // { // PRINT(("\t%s: %s\n", lpMetaData->name, lpMetaData->content)) // lpMetaData = lpMetaData->next; // } // // lpMetaData = FindMeta(MetaList, "Content-Location"); // if(lpMetaData == NULL) // { // PRINT(("Meta Content-location unavailable, file name is unknown, can't save...\n")) // } // else { // ASSERT(!strcmp(file_name, lpMetaData->content)) // if((lpMetaData = FindMeta(MetaList, "Content-Base"))!=NULL) // ASSERT(!strcmp(file_base, lpMetaData->content)) // else // ASSERT(!strcmp(file_base, "./")) // } // // FragLength = len -8 -trailerlength; // // if((lpMetaData = FindMeta(MetaList, "Content-Length"))!=NULL) // { // if( lpMetaData->value != (long)FragLength ) // PRINT(("Warning: Size of ffragment received and \"Content-length\" value doesn't match! (%ld!=%ld)\n",lpMetaData->value, FragLength)) // } // if((lpMetaData = FindMeta(MetaList, "Content-Filesize"))!=NULL) // { // ASSERT(FileLength == lpMetaData->value) // } // else // { // EXIT(("Error: Missing Meta Content-Filesize")) // } // // lpMetaData = FindMeta(MetaList, "Content-Fragment"); // if(lpMetaData == NULL) // { // EXIT(("Error: Meta Content-Fragment unavailable\n")) // } // else // { char *token; // token = strtok( lpMetaData->content, "/" ); // if( token != NULL ) // { // CurrFrag = atoi(token); // token = strtok( NULL, "/" ); // if( token != NULL ) // TotFrag = atoi(token); // else // EXIT(("Error: Invalide Meta (Content-Fragment)\n")) // } // else // EXIT(("Error: Invalide Meta (Content-Fragment)\n")) // // PRINT(("Processing fragment %d of file %s (%d fragments)\n", CurrFrag, file_path, TotFrag)) // lpMetaData = FindMeta(MetaList, "Content-Offset"); // if(lpMetaData == NULL) // { // EXIT(("Error: Meta Content-Offset unavailable\n")) // } // else // { // offset = lpMetaData->value; // PRINT(("\tWriting %ld bytes at offset %d\n", FragLength, offset)) // // if (lseek((int)saved_file, (long)offset, SEEK_SET) < 0) // EXIT(("Error: lseek failed\n")) // if (write((int)saved_file, buf_file, FragLength) < 0) // EXIT(("mclrecv: write failed\n")) // received += len; // // } // } // DestroyMetalist(MetaList); // IndFrag++; // } // // // PRINT(("File \"%s\" saved (%d Bytes).\n", file_path, FileLength)) // close(saved_file); // } // } // else // { // PRINT(("File \"%s\" skipped (%d Bytes).\n", file_path, FileLength)) // received = -1; // } // //end: // if(buf_file) free(buf_file); // // return received; //}