#pragma module RETRACKER "RETRACKER-1-X" /* **++ ** FACILITY: bitTorrent Retracker ** ** MODULE DESCRIPTION: ** ** {tbs} ** ** AUTHORS: ** ** Ruslan R. Laishev ** ** CREATION DATE: 31-MAR-2010 ** ** DESIGN ISSUES: ** ** This module use a WASD CGIplus technology. List of Environment/Form element/variables: ** ** ** ** ** ** ** MODIFICATION HISTORY: ** ** ** {@tbs@}... **-- */ /* ** ** INCLUDE FILES ** */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define __NEW_STARLET 1 #include #include #include #include #include "cgilib.h" #include "btdef.h" #define INIT_SDESC(dsc, len, ptr) {(dsc).dsc$b_dtype = DSC$K_DTYPE_T;\ (dsc).dsc$b_class = DSC$K_CLASS_S; (dsc).dsc$w_length = (short) (len);\ (dsc).dsc$a_pointer = (ptr);} struct FAB fab; struct RAB rab; #define true 1 #define false 0 int DebugWatch = 0; $DESCRIPTOR(tmo_dsc,"0 01:30:00"); unsigned __int64 tmo = 0; /* **++ ** FUNCTIONAL DESCRIPTION: ** ** The main start procedure, perform a CGIplus specific initialization. ** ** DESIGN: ** A behaviour of this script is controled by logical RETRACKER$WATCH. ** **-- */ int main (void) { int status,IsCgiPlus = 0; char *cp; /* ** CGIPlus Initialization */ DebugWatch = (NULL != getenv ("RETRACKER$WATCH")); CgiLibEnvironmentSetDebug (DebugWatch); CgiLibEnvironmentInit (0, NULL, false); IsCgiPlus = CgiLibEnvironmentIsCgiPlus (); /* ** */ sys$bintim(&tmo_dsc,&tmo); /* ** */ fab = cc$rms_fab; fab.fab$b_fac = FAB$M_GET | FAB$M_PUT | FAB$M_UPD | FAB$M_DEL; fab.fab$b_shr = FAB$M_SHRGET | FAB$M_SHRPUT | FAB$M_SHRDEL | FAB$M_SHRUPD | FAB$M_NQL; fab.fab$l_fna = "RETRACKER"; fab.fab$b_fns = 9; fab.fab$l_dna = ".DAT"; fab.fab$b_dns = 4; if ( !(1 & (status = sys$open(&fab))) ) return lib$signal(status,fab.fab$l_stv); rab = cc$rms_rab; rab.rab$l_fab = &fab; rab.rab$b_rac = RAB$C_KEY; rab.rab$v_wat = rab.rab$v_rah = 1; rab.rab$b_tmo = 5; if ( !(1 & (status = sys$connect(&rab))) ) return lib$signal(status,rab.rab$l_stv); /* ** Main processing block/loop */ do { /* ** with CGIplus this call will block waiting for the next request */ CgiLibVar (""); rab.rab$v_nlk = 0; Dispatcher(); sys$free(&rab); purge(); if ( IsCgiPlus ) CgiLibCgiPlusEOF (); } while ( IsCgiPlus ); sys$close(&fab); return SS$_NORMAL; } $DESCRIPTOR(path_dsc, "WWW_PATH_INFO"); $DESCRIPTOR(anno_dsc, "/announce"); $DESCRIPTOR(slash_dsc, "/"); void Dispatcher (void) { int status; char buf[1024]; struct dsc$descriptor junk; INIT_SDESC(junk,sizeof(buf),buf); if ( !(1 & (status = CgiLibVarByDesc(&path_dsc,&junk,&junk.dsc$w_length))) ) return lib$signal(status); if ( !str$case_blind_compare(&anno_dsc,&junk) ) return announce(); if ( !str$case_blind_compare(&slash_dsc,&junk) ) return dump(); } void bin2hex ( unsigned char * sts, unsigned char * bin, unsigned short len ) { char l,h; for(;len;len--,sts += 2,bin++) { h = (*bin) >>4; l = (*bin) & 0x0F; *sts = (h < 10)?h + '0':h + 'a' - 10; *(sts+1)= (l < 10)?l + '0':l + 'a' - 10; } } void dump (void) { int status; char buf[1024],hash[128]; BT_REC rec; struct dsc$descriptor junk; struct in_addr in; $DESCRIPTOR(html_hdr, "Content-Type: text/html\rPragma: no-cache\r\n\r\n\
\\ \ \ \ \ \ "); $DESCRIPTOR(html_row, "\ \ \ \ \ \ "); $DESCRIPTOR(html_end, "

#

TTH

IP:Port

Last updated

!UL

!AZ

!AZ:!UW

!%D

"); /* ** Prepare to reading from the retracker database file */ rab.rab$l_ubf = &rec; rab.rab$w_usz = sizeof(BT_REC); rab.rab$b_rac = RAB$C_SEQ; rab.rab$v_nlk = 1; sys$rewind(&rab); lib$put_output(&html_hdr); for ( int i = 0; 1 & (status = sys$get (&rab)); i++) { memset(hash,0,sizeof(hash)); bin2hex(&hash,&rec.bt$b_hash,sizeof(rec.bt$b_hash)); in.S_un.S_addr = rec.bt$l_ip; INIT_SDESC(junk,sizeof(buf),buf); sys$fao(&html_row,&junk.dsc$w_length,&junk,i,hash, inet_ntoa(in),rec.bt$w_port,&rec.bt$q_updtm); lib$put_output(&junk); } lib$put_output(&html_end); if ( status == RMS$_EOF ) return; return lib$signal(status,rab.rab$l_stv); } /* GET /announce?info_hash=%db.%10%e5%23%be%15H%9b%d0%d4%40n%0a%ba%d2%dd%a4%26%06 &peer_id=-UT2000-8Hl%f2%3fIJwy%87%0c%26&port=37279&uploaded=471687432 &downloaded=0&left=0&corrupt=0&key=B3785E01&numwant=200&compact=1&no_peer_id=1 */ $DESCRIPTOR(hash_dsc, "WWW_FORM_INFO_HASH"); void announce (void) { int status; char buf[8192],*cp; BT_REC rec,*recp = (BT_REC *) buf;; struct dsc$descriptor junk; const char html_hdr [] = "Content-Type: text/html\r\n\ Transfer-Encoding: chunked\r\n\ Script-Control: X-stream-mode\r\n\ Pragma: no-cache\r\n\r\n36\r\n", html_row [] = "d8:intervali2024e12:min intervali1500e5:peers6:", html_end [] = "\r\n0\r\n\r\n"; memset(&rec,0,sizeof(rec)); INIT_SDESC(junk,sizeof(rec.bt$b_hash),rec.bt$b_hash); if ( !(1 & (status = CgiLibVarByDesc(&hash_dsc,&junk,&junk.dsc$w_length))) ) return lib$signal(status); if ( !(cp = CgiLibVar("WWW_REMOTE_ADDR")) ) return; inet_aton(cp,&rec.bt$l_ip); if ( !(cp = CgiLibVar("WWW_FORM_PORT")) ) return; rec.bt$w_port = htons(atoi(cp)); sys$gettim(&rec.bt$q_updtm); /* ** Put/Update peer information */ rab.rab$b_rac = RAB$C_KEY; rab.rab$l_rbf = &rec; rab.rab$w_rsz = sizeof(BT_REC); rab.rab$v_uif = 1; if ( !(1 & (status = sys$put (&rab))) ) lib$signal(status,rab.rab$l_stv); if ( !(1 & (status = sys$flush (&rab))) ) lib$signal(status,rab.rab$l_stv); /* ** Dump the list of peer with the target torrent's hash */ rab.rab$l_ubf = buf; rab.rab$w_usz = sizeof(buf); rab.rab$b_krf = 0; rab.rab$b_ksz = sizeof(rec.bt$b_hash); rab.rab$l_kbf = &rec; if ( !(1 & (status = sys$get (&rab))) ) return lib$signal(status,rab.rab$l_stv); rab.rab$v_lim = 1; rab.rab$b_ksz++; rab.rab$b_rac = RAB$C_SEQ; fwrite(html_hdr,sizeof(html_hdr)-1,1,stdout); fflush(stdout); CgiLibResponseSetRecordMode (false); CgiLibResponseSetStreamMode (true); for ( int i = 0; i < 200; i++) { fwrite(html_row,sizeof(html_row)-1,1,stdout); fwrite(&recp->bt$r_sock,sizeof(recp->bt$r_sock),1,stdout); fwrite("e",1,1,stdout); if ( !(1 & (status = sys$get (&rab))) || (status == RMS$_OK_LIM) ) break; } fwrite(html_end,sizeof(html_end)-1,1,stdout); fflush(stdout); if ( (status == RMS$_OK_LIM) || (status == RMS$_EOF) ) return; return lib$signal(status,rab.rab$l_stv); } $DESCRIPTOR(res_dsc,"BT$RETRACKER"); void purge (void) { int status; BT_REC rec; unsigned __int64 ctm; LKSB lksb; /* ** Try to get an exclusive access to performs purge ** action */ if ( !(1 & (status = sys$enqw (EFN$C_ENF, LCK$K_EXMODE, &lksb, LCK$M_NOQUEUE,&res_dsc,0,0,0,0,0,0))) ) return; sys$gettim(&ctm); lib$sub_times (&ctm,&tmo,&ctm); rab.rab$b_rac = RAB$C_SEQ; rab.rab$l_ubf = &rec; rab.rab$w_usz = sizeof(rec); sys$rewind(&rab); while ( 1 & (status = sys$get(&rab)) ) if ( rec.bt$q_updtm < ctm ) if ( !(1 & (status = sys$delete(&rab))) ) break; if ( status != RMS$_EOF ) {int msgvec[] = {2,status,rab.rab$l_stv}; sys$putmsg(&msgvec,0,0,0); } /* ** Free */ status = sys$deq(lksb.lksb$l_lkid,0,0,0); }