int main(int argc, char **argv) { //initial the client if (argc>1) port = atoi(argv[1]); int info_fd = client_init(SERVER_IP); char filename[FILENAME_MAXLEN] = {0}; printf("BLOCKSIZE= %d\n",BLOCKSIZE); printf("Input filename : "); scanf("%s",filename); int fd=0; if((fd = open(filename, O_RDWR)) == -1 ) { printf("open erro !\n"); exit(-1); } /*Timer*/ printf("Timer start!\n"); time_t t_start, t_end; t_start=time(NULL); //send file info struct stat filestat; fstat(fd ,&filestat); int last_bs=0; struct fileinfo finfo; send_fileinfo(info_fd, filename, &filestat, &finfo, &last_bs); // char id_buf[INT_SIZE] = {0}; int n=0; for(n=0; n<INT_SIZE; n++){ read(info_fd, &id_buf[n], 1); } int freeid = *((int *)id_buf); printf("freeid = %d\n", freeid); //map . mbegin = (char *)mmap(NULL, filestat.st_size, PROT_WRITE|PROT_READ, MAP_SHARED, fd , 0); close(fd); //add task to the list int j=0, num=finfo.count, offset=0; pthread_t pid[num]; memset(pid, 0, num*sizeof(pthread_t)); int head_len = sizeof(struct head); // file can be slipt into blocks if(last_bs == 0){ for(j=0; j<num; j++){ struct head * p_fhead = new_fb_head(filename, freeid, &offset); if (pthread_create(&pid[j], NULL, send_filedata, (void *)p_fhead) != 0){ printf("%s:pthread_create failed, errno:%d, error:%s\n", __FUNCTION__, errno, strerror(errno)); exit(-1); } } } //file cannot slipt into blocks else{ for(j=0; j<num-1; j++){ struct head * p_fhead = new_fb_head(filename, freeid, &offset); if (pthread_create(&pid[j], NULL, send_filedata, (void *)p_fhead) != 0){ printf("%s:pthread_create failed, errno:%d, error:%s\n", __FUNCTION__, errno, strerror(errno)); exit(-1); } } //the last block struct head * p_fhead = (struct head *)malloc(head_len); bzero(p_fhead, head_len); strcpy(p_fhead->filename, filename); p_fhead->id = freeid; p_fhead->offset = offset; p_fhead->bs = last_bs; if (pthread_create(&pid[j], NULL, send_filedata, (void *)p_fhead) != 0){ printf("%s:pthread_create failed, errno:%d, error:%s\n", __FUNCTION__, errno, strerror(errno)); exit(-1); } } //join all the pthread for (j = 0; j < num; ++j) { pthread_join(pid[j], NULL); } //calculate the time for send file t_end=time(NULL); printf("Master prosess exit!\n"); printf("TIME:%.0fs\n",difftime(t_end,t_start)); return 0; }
/** * Perform the Announce/Register phase for a particular group/file * Group & encryption: ->ANNOUNCE <-REGISTER ->KEYINFO <-INFO_ACK * Group & no encryption: ->ANNOUNCE <-REGISTER ->REG_CONF * Files within a group: ->FILEINFO <-INFO_ACK * If client_key == 1, REGISTER is followed by CLIENT_KEY * Returns 1 if at least one client responded, 0 if none responded */ int announce_phase(struct finfo_t *finfo) { time_t endtime; int attempt, resend, announce, regconf, keyinfo, fileinfo, open, anyerror; int len, rval, rcv_status, last_pass, gotall, gotone, allreg, regdone, i; unsigned char *packet, *decrypted; struct uftp_h *header; struct timeval timeout; struct sockaddr_in receiver; if (finfo->file_id) { log1(0, 0, "File ID: %04X Name: %s", finfo->file_id, finfo->filename); log1(0, 0, " sending as: %s", finfo->destfname); switch (finfo->ftype) { case FTYPE_REG: log(0, 0, "Bytes: %s Blocks: %d Sections: %d", printll(finfo->size), finfo->blocks, finfo->sections); break; case FTYPE_DIR: log(0, 0, "Empty directory"); break; case FTYPE_LINK: log(0, 0, "Symbolic link to %s", finfo->linkname); break; } } else { log(0, 0, "Initializing group"); if (sync_mode) { log0(0, 0, "- Connect -"); } } rval = 1; packet = calloc(mtu, 1); decrypted = calloc(mtu, 1); if ((packet == NULL) || (decrypted == NULL)) { syserror(0, 0, "calloc failed!"); exit(1); } header = (struct uftp_h *)packet; endtime = time(NULL) + announce_time; announce = (finfo->file_id == 0); regconf = (announce && (keytype == KEY_NONE)); keyinfo = (announce && (keytype != KEY_NONE)); fileinfo = (finfo->file_id != 0); open = (destcount == 0); for (i = 0; i < destcount; i++) { // At start of group, initialize all clients/proxies to DEST_MUTE. // At start of file, initialize proxies to DEST_ACTIVE (since they // don't respond directly to a FILEINFO) and clients to DEST_REGISTERED. if (announce) { destlist[i].status = DEST_MUTE; } else if (!client_error(i)) { if (destlist[i].clientcnt != -1) { destlist[i].status = DEST_ACTIVE; } else { destlist[i].status = DEST_REGISTERED; } } } timeout.tv_sec = announce_int / 1000; timeout.tv_usec = (announce_int % 1000) * 1000; resend = 1; attempt = 1; last_pass = 0; regdone = 0; while (time(NULL) < endtime) { // On the initial pass, or when the announce timeout trips, // send any necessary messages. if (resend) { if (keyinfo && !send_keyinfo(finfo, attempt)) { continue; } if (announce && !send_regconf(finfo, attempt, regconf)) { continue; } if (fileinfo && !send_fileinfo(finfo, attempt)) { continue; } if (announce && !send_announce(finfo, attempt, open)) { continue; } resend = 0; } // TODO: Currently, the interval between sends is really an inactivity // timer, not the actual time between sends. We might want to change // it to that, and perhaps add an extra "overage" timer in case we're // still processing responses when we're due to resend, that way we'll // always wait some minimum amount of time. if ((rcv_status = read_packet(sock, &receiver, packet, &len, mtu, &timeout)) == -1) { continue; } else if (rcv_status == 0) { attempt++; resend = 1; if (last_pass) break; continue; } if (!validate_packet(packet, len, finfo)) { continue; } if (!handle_announce_phase(packet, decrypted, &receiver, finfo, announce, open, regconf)) { continue; } if (!open) { for (i = 0, gotall = 1, allreg = 1; (i < destcount) && (gotall || allreg); i++) { if (announce) { gotall = gotall && ((destlist[i].status == DEST_ACTIVE) || (destlist[i].status == DEST_ABORT)); allreg = allreg && ((destlist[i].status == DEST_ACTIVE) || (destlist[i].status == DEST_REGISTERED) || (destlist[i].status == DEST_ABORT)); } else { gotall = gotall && ((destlist[i].status == DEST_ACTIVE) || (destlist[i].status == DEST_DONE) || (client_error(i))); } } if (gotall) { // Break out right away if this is a file registration. // For group registration, do one last wait, even if // encryption is enabled since we can still send a // REG_CONF for a client behind a proxy. // Change the wait interval to the client's register_int * 1.5 // to allow for late registers. // Be careful not to overrun the phase timeout! if (finfo->file_id != 0) break; timeout.tv_sec = (int)(register_int / 1000 * 1.5); timeout.tv_usec = (int)((register_int % 1000) * 1000 * 1.5); if (timeout.tv_sec > endtime) { #ifdef WINDOWS timeout.tv_sec = (long)endtime; #else timeout.tv_sec = endtime; #endif timeout.tv_usec = 0; } if (!last_pass) { log(0, 0, "Late registers:"); } last_pass = 1; send_regconf(finfo, attempt + 1, regconf); } else if (announce && allreg && !regdone) { // All have registered, so don't wait to send the next message resend = 1; regdone = 1; } } } for (i = 0, gotone = 0, anyerror = 0; i < destcount; i++) { gotone = gotone || (((destlist[i].status == DEST_ACTIVE) || (destlist[i].status == DEST_DONE)) && (destlist[i].clientcnt == -1)); if (destlist[i].status == DEST_REGISTERED) { log1(0, 0, "Couldn't get INFO_ACK from %s", destlist[i].name); destlist[i].status = DEST_LOST; anyerror = 1; } if ((destlist[i].status == DEST_MUTE) || (destlist[i].status == DEST_ABORT)) { anyerror = 1; } } if (anyerror && quit_on_error) { log0(0, 0, "Aboring all clients"); send_abort(finfo, "A client dropped out, aborting all", &receive_dest, NULL, (keytype != KEY_NONE), 0); for (i = 0; i < destcount; i++) { if (destlist[i].status == DEST_ACTIVE) { destlist[i].status = DEST_ABORT; } } rval = 0; } if (!gotone) { log0(0, 0, "Announce timed out"); rval = 0; } if (open) { send_regconf(finfo, attempt, regconf); } if ((finfo->file_id == 0) && sync_mode) { for (i = 0; i < destcount; i++) { if (destlist[i].status == DEST_ACTIVE) { log0(0, 0, "CONNECT;success;%s", destlist[i].name); } else { log0(0, 0, "CONNECT;failed;%s", destlist[i].name); } } log0(0, 0, "- Transfer -"); } free(packet); free(decrypted); return rval; }