import Protocols.Bittorrent; Torrent t=Torrent(); function(int,int:void) progress(string name,int steps) { int inited=0; int lastpos=0; return lambda(int n,int m) { if (!inited) write(name+"["+"."*steps+"]\r"+name+"["),inited=1; int pos=(steps*n)/m; if (pos!=lastpos) { write("#"*(pos-lastpos)); lastpos=pos; } if (n==m) write("\n"); }; } int at_line=0; int total_lines=5; int error_lines=3; void goto_line(int n) { if (n==at_line) { write("\r"); return; } while (n>at_line) write("\n"),at_line++; while (nfile_got); string res=sprintf("done: %3d%% {",sizeof(t->file_got-({0}))*100/z); for (int i=0; ifile_got[pos..npos-1])*1.0/(npos-pos); if (q==0.0) res+=" "; else if (q<0.25) res+="."; else if (q<0.5) res+="o"; else if (q<0.75) res+="O"; else if (q<1.0) res+="@"; else res+="#"; } write(res+"}\n"); at_line++; } string t_reset="\33[0m"; string t_connecting="\33[36m"; string t_ok="\33[36m"; string t_avail="\33[32m"; string t_choked="\33[31m"; string t_strangled="\33[34m"; string t_choked_n_strangled="\33[35m"; string t_dead="\33[30m"; string t_working_with="\33[1m"; string t_background="\33[40m"; string t_handover="\33[5m"; string td_choked="\33[31m"; string td_strangled="\33[34m"; string td_strangled_download="\33[36m"; string td_choked_n_strangled="\33[35m"; string td_download=""; // string t_strangle="\33[44m"; // string t_choking="\33[1;31m"; void show_downloads() { goto_line(0); int len=64; int z=sizeof(t->file_got); string res=sprintf("transfer: {"+t_background); multiset uls=`+((<>),@t->peers_ordered->uploading_pieces); multiset stgs=`+((<>),@filter(t->peers_ordered,"is_strangled") ->uploading_pieces); multiset chkd=`+((<>),@filter(t->peers_ordered,"is_choked") ->downloading_pieces()); for (int i=0; ifile_downloading,pos,npos,enumerate(pos,1,npos-pos)); array(int) us=enumerate(npos-pos,1,pos); multiset(int) mus=(multiset)us; int dl=sizeof(t->downloads & us); int ul=sizeof(uls & mus); int st=sizeof(stgs & mus); int ch=sizeof(chkd & mus); int lost=sizeof(t->lost_in_space & us); int hand=sizeof(t->handovers & us); string sym; if (ul && dl) sym="X"; else if (ul) sym="^"; else if (dl || hand) sym="v"; else if (lost) sym="-"; else sym=" "; if (hand) sym=t_handover+sym; if (st && st==ul) if (ch && ch==dl) sym=td_choked_n_strangled+sym; else if (dl) sym=td_strangled_download+sym; else sym=td_strangled+sym; else if (ch && ch==dl) sym=td_choked+sym; else if (dl) sym=td_download+sym; if (strlen(sym)>1) sym+=t_reset+t_background; res+=sym; } write(res+t_reset+"}\n"); at_line++; show_peers(); } void show_peers() { goto_line(2); array p=copy_value(t->peers_ordered); // sort(p->ip,p); string res=sprintf("peers:%4d >",sizeof(p))+t_background; // werror("%O\n",t->activated_peers); int i=0; int l=0; array text= ({sprintf("online:%3d ",sizeof(filter(p,"is_online")))})+ ({" "})*30; foreach (p;;Peer p) { if ((<"dead","disconnected","failed">)[p->mode] && find_call_out(p->connect)==-1) continue; if (i==64) { res+=t_reset+"< \n"+text[l]+">"+t_background; l++; i=0; } if (p->online<2 && (<"incoming","connecting","connected">)[p->mode]) res+=t_connecting; else if (p->peer_choking) if (p->strangled) res+=t_choked_n_strangled; else res+=t_choked; else if (p->strangled) res+=t_strangled; else if (p->is_available()) res+=t_avail; else if (p->online<2) if ((<"incoming","connecting","connected","online">)[p->mode]) res+=t_connecting; else res+=t_dead; else res+=t_ok; if (p->uploading || p->is_activated()) res+=t_working_with; switch (p->mode) { case "online": if (p->is_activated()) if (p->is_complete) res+="V"; else if (p->uploading) res+="X"; else res+="v"; else if (p->uploading) res+="^"; else if (p->is_complete) res+="S"; else if (p->peer_interested) res+="i"; else if (p->bitfield==t->no_pieces_bits) res+="e"; else res+="o"; break; default: if (p->is_activated()) werror("%O is activated but %O\n",p,p->mode); res+=(["created":"-", "connecting":"c", "connected":"C", "incoming":"I", "failed":"f", "dead":"D", "disconnected":"d"])[p->mode]||("("+p->mode+")"); } if (p->uploading || p->is_activated()) res+=t_reset+t_background; ++i; } write(res+t_reset+"< \n"); while (l<1) write(text[l++]+"\n"); at_line+=l+1; if (at_line>total_lines) error_lines-=(at_line-total_lines),total_lines=at_line; else while (at_linepeers),"is_online"); goto_line(total_lines); multiset uls=`+((<>),@t->peers_ordered->uploading_pieces); multiset suls=`+((<>), @filter(t->peers_ordered,"is_strangled") ->uploading_pieces); int bandwidth_in=`+(0,@p->bandwidth_in); big_mean+=({bandwidth_in}); big_mean=big_mean[sizeof(big_mean)-600..]; // 10 minutes int bandwidth_mean=`+(@big_mean)/sizeof(big_mean); write("down:%7.3fkb/s (%7.3fkb/s) up:%7.3fkb/s " "dls/uls(str):%3d/%3d(%3d) \n", bandwidth_in*0.001,bandwidth_mean*0.001, `+(0,@p->bandwidth_out)*0.001, sizeof(t->downloads)+sizeof(t->handovers), sizeof(uls-suls), sizeof(suls)); int tleft=t->bytes_left()/(bandwidth_mean||1); Calendar.Second tdone=Calendar.Second()+tleft; write("total: %sb left: %*sb %d:%02d:%02d (done %s %d:%02d:%02d) \n", ((string)t->total_bytes)/-3.0*",", strlen((string)t->total_bytes/-3.0*","), ((string)t->bytes_left())/-3.0*",", tleft/3600, tleft/60%60, tleft%60, tdone->week_day_shortname(), tdone->hour_no(), tdone->minute_no(), tdone->second_no()); at_line+=2; } int main(int ac,array am) { t=Torrent(); t->load_metainfo(am[1]); t->downloads_update_status=show_downloads; t->pieces_update_status=show_status; t->peer_update_status=show_peers; t->download_completed_callback= lambda() { call_out(exit_program,30,0); }; t->warning=lambda(string s,mixed ...args) { goto_line(error_lines+total_lines); write(s=sprintf(s,@args)); error_lines+=1+strlen(s)/80; at_line++; }; if (t->fix_targets(1,0,progress("allocating ",64))==1) t->verify_targets(progress("verifying ",64)); t->my_port=6881; t->open_port(); write("\n"); signal(signum("SIGINT"),exit_program); signal(signum("SIGKILL"),exit_program); show_status(); t->max_peers=200; t->start_update_tracker(); t->update_tracker(0,1); // one more time to get more peers t->update_tracker(0,1); // one more time to get more peers t->update_tracker(0,1); // one more time to get more peers show_peers(); t->start_download(); call_out(bandwidth_info,0.5); return -1; } void exit_program() { goto_line(error_lines+total_lines); exit(0); }