001 class CDCCTransfer { 002 //bit0 is usage lock 003 //bit1 is done reciveing data flag 004 I64 lock; 005 I64 writer,accept,reader; 006 I64 port; 007 I64 fsz,token; 008 IrcClient *notify_to; 009 U8 name[STR_LEN]; 010 U8 username[STR_LEN]; 011 }; 012 #define DCC_PORT_START 6000 013 #define DCC_PORT_END 6100 014 015 #define DCC_DIR "T:/GihonFiles" 016 CDCCTransfer dcc_transfers[0x10000];; 017 MemSet(dcc_transfers,0,sizeof(CDCCTransfer)*0x1000); 018 I64 HashFile(U8 *data,I64 len) { 019 I64 res=5381; 020 while (--len>=0) 021 res+=(res<<5)+res+data[len]; 022 return res; 023 } 024 U0 FilesTimeoutTask(U8 *dir) { 025 CDirEntry *root,*cur; 026 while(TRUE) { 027 root=FilesFind(dir,FUF_JUST_FILES|FUF_FLATTEN_TREE|FUF_RECURSE); 028 for(cur=root;cur;cur=cur->next) { 029 if(Now>cur->datetime+CDATE_FREQ*(60*60*24)) { 030 DbgPrint("Deleting '%s'\n",cur->full_name); 031 Del(root->full_name); 032 } 033 } 034 DirEntryDel(root); 035 Sleep(10000); 036 } 037 } 038 U8 *DCCSaveFile(U8 *want_name,U8 *data,I64 len) { 039 U8 *ext,*actual; 040 if(!FileFind("T:/HTML/IRC")) { 041 DirMk("T:/HTML"); 042 DirMk("T:/HTML/IRC"); 043 } 044 if(CDIR_FILENAME_LEN<StrLen(want_name)) { 045 ext=FileExtDot(want_name); 046 if(!ext) ext=""; 047 actual=MStrPrint("%X%s",HashFile(data,len),ext); 048 want_name=MStrPrint("T:/HTML/IRC/%s.Z",actual); 049 } else want_name=MStrPrint("T:/HTML/IRC/%s.Z",want_name),actual=StrNew(want_name); 050 FileWrite(want_name,data,len); 051 Free(want_name); 052 return actual; 053 } 054 //Use FramePtr("send_data"); 055 U0 DCCSendTask(I64 to_sock) { 056 U8 *data=FramePtr("send_data"); 057 I64 flen=FramePtr("send_size"),ptr=0; 058 I64 cnt,written; 059 U32 ass; 060 while(flen-ptr>0) { 061 written=send(to_sock,data+ptr,flen-ptr,0); 062 Sleep(1); 063 if(written<0) 064 break; 065 recv(to_sock,&ass,4,0); 066 written=EndianU32(ass); 067 ptr=written; 068 } 069 Sleep(1000); 070 close(to_sock); 071 } 072 U0 DCCRecvTask(I64 port) { 073 CDCCTransfer *t=&dcc_transfers[port]; 074 F64 kill_at=tS+21.; 075 U8 *path; 076 I64 cnt=0,ptr; 077 I64 flen=t->fsz; 078 U8 *data,*file_notice; 079 CFile *f; 080 IrcClient *to_client; 081 path=MStrPrint(DCC_DIR"/%s",t->name); 082 if(!FileFind(DCC_DIR)) DirMk(DCC_DIR); 083 084 I32 to=EndianU32(NetIP4ByHost(ircd_hostname)); 085 DbgPrint("POOPASS:%d\n",to); 086 path=MStrPrint(":%s!%s@0 PRIVMSG %s :\x01DCC SEND %s %d %d %d %d\x01\r\n", 087 t->username, 088 t->username, 089 t->notify_to->nick, 090 t->name, 091 to, 092 port, 093 t->fsz, 094 t->token 095 ); 096 GihonFifoIns( 097 t->notify_to->msgs, 098 path 099 ); 100 101 102 while(TRUE) { 103 if(kill_at<tS) { 104 close(t->accept); 105 LBtr(&t->lock,1); 106 Exit; 107 } 108 t->writer=accept(t->accept,NULL,0); 109 if(t->writer!=-1) 110 break; 111 else 112 Sleep(10); 113 } 114 U32 poo; 115 data=CAlloc(t->fsz+1); 116 ptr=0; 117 flen=t->fsz; 118 while(flen-ptr>0&&(cnt=recv(t->writer,data+ptr,flen-ptr,0))>0) { 119 ptr+=cnt; 120 poo=EndianU32(ptr); 121 send(t->writer,&poo,4,0); 122 Sleep(1); 123 } 124 125 path=DCCSaveFile(t->name,data,t->fsz); 126 file_notice=MStrPrint("File also available at ' %s/IRC/%s ' (Deleted after awhile deleted after 24 hours).",ircd_hostname,path); 127 IrcClientNotice(t->notify_to,file_notice); 128 Free(path); 129 130 path=MStrPrint(":%s!%s@0 PRIVMSG %s :\x01DCC SEND %s %d %d %d\x01\r\n", 131 t->notify_to->nick, 132 t->notify_to->nick, 133 t->username, 134 t->name, 135 to, 136 port, 137 t->fsz, 138 t->token 139 ); 140 close(t->writer); 141 close(t->accept); 142 143 t->accept=create_server("0.0.0.0",port,21); 144 if(to_client=IrcGetClientByNick(t->username)) { 145 FramePtrAdd("send_data",data); 146 FramePtrAdd("send_size",t->fsz); 147 GihonFifoIns(to_client->msgs,StrNew(path)); 148 Free(path); 149 //PRIVMSG the file link to the user 150 path=MStrPrint(":%s!%s@0 PRIVMSG %s :%s\r\n", 151 t->notify_to->nick, 152 t->notify_to->nick, 153 t->username, 154 file_notice 155 ); 156 GihonFifoIns(to_client->msgs,StrNew(path)); 157 158 kill_at=tS+120; 159 while(TRUE) { 160 if(kill_at<tS) { 161 close(t->accept); 162 LBtr(&t->lock,1); 163 Exit; 164 } 165 t->reader=accept(t->accept,NULL,0); 166 if(t->reader!=-1) { 167 Spawn(&DCCSendTask,t->reader,,,Fs); 168 } else 169 Sleep(10); 170 } 171 } else 172 Free(path); 173 174 close(t->accept); 175 Free(data); 176 Free(file_notice); 177 LBtr(&t->lock,1); 178 } 179 Bool DCC_ReverseSendTo(U8 *fn,I64 notify,I64 port=DCC_PORT_START,U8 *to,U8 *fsz,U8 *token) { 180 CDCCTransfer *t=&dcc_transfers[port]; 181 LBts(&t->lock,1); 182 I64 writer=-1,reader=-1; 183 I64 sock=create_server("0.0.0.0",port,1); 184 StrCpy(t->name,fn); 185 StrCpy(t->username,to); 186 t->notify_to=notify; 187 t->fsz=Str2I64(fsz); 188 if(token) t->token=Str2I64(token); else t->token=0; 189 t->accept=sock; 190 LBts(&t->lock,1); 191 Spawn(&DCCRecvTask,port,,,Fs); 192 return TRUE; 193 } 194 I64 DCCPickPort() { 195 I64 s=DCC_PORT_START; 196 while(s<DCC_PORT_END) { 197 if(!Bt(&dcc_transfers[s].lock,1)) 198 return s; 199 s++; 200 } 201 return -1; //DCC_PORT_END 202 } 203 U0 IrcDCCSend(IrcClient *cl,U8 *to,U8 *fn,U8 *host,U8 *portname,U8 *fsz,U8 *token) { 204 U8 *path; 205 I64 port=Str2I64(portname); 206 I64 sock,len,total; 207 CFile *f; 208 if(!fsz) { 209 IrcClientNotice(to,"Specify a file size"); 210 return; 211 } 212 if(!FileFind(DCC_DIR)) DirMk(DCC_DIR); 213 path=MStrPrint(DCC_DIR"/%s",fn); 214 if(Str2I64(fsz)>1000*1000*100) { 215 IrcClientNotice(to,"Thats a fuckin huge file."); 216 return; 217 } 218 port=DCCPickPort; 219 if(port!=-1) 220 DCC_ReverseSendTo(fn,cl,port,to,fsz,token); 221 Free(path); 222 } 223 Bool IsDccCommand(IrcClient *cl,U8 *to,U8 *msg) { 224 I64 argc; 225 U8 **argv; 226 Bool ret=FALSE; 227 if(msg[0]==1) { 228 ++msg; 229 if(StrOcc(msg,1)) StrFirstOcc(msg,"\x01")[0]=0; 230 argv=ParseArgs(msg,&argc); 231 if(argc>=6&&!StrCmp(argv[0],"DCC")) { 232 ret=TRUE; 233 if(!StrCmp(argv[1],"SEND")) { 234 if(argc>=6) { //DCC command ip port 235 DbgPrint("DCC INIT to %s(%s)\n",to,argv[2]); 236 if(argc>=7) 237 IrcDCCSend(cl,to,argv[2],"0","0",argv[5],argv[6]); 238 else 239 IrcDCCSend(cl,to,argv[2],"0","0",argv[5],NULL); 240 ret=TRUE; 241 } 242 } 243 } 244 FreeArgs(argc,argv); 245 } 246 return ret; 247 } 248 Spawn(&FilesTimeoutTask,"T:/HTML/IRC",,,Fs);