#include #include #include #include #include #include #include #include #include #include #ifdef DMALLOC #include #endif #ifdef SOCKS #include #endif #include "serverdcc.h" #include "window.h" #include "support.h" #include "echo.h" #include "config.h" #include "tcltk.h" #include "quirc.h" #include "format.h" // Port 59 is what mIRC listens on for incoming connections // Add error checking on close // Add no connect warnings to sendata et all. tdcc::~tdcc() { free(nick); Tcl_DeleteFileHandler(sockfd); } void tdcc::perror(char *message) { int number=errno; char num[100]; if(type==DCCFILEGET||type==DCCFILESEND) { sprintf(num,"%d",index); fdisplay("DCC_FILE_ERROR",server->index,3,num,message,strerror(number)); } else { fdisplay("DCC_ERROR",server->index,3,pathname,message,strerror(number)); } } void tdcc::perror(char *message, int number) { char num[100]; if(type==DCCFILEGET||type==DCCFILESEND) { sprintf(num,"%d",index); fdisplay("DCC_FILE_ERROR",server->index,3,num,message,strerror(number)); } else { fdisplay("DCC_ERROR",server->index,3,pathname,message,strerror(number)); } } void tdcc::filemessage(char *message) { char temp[1000]; sprintf(temp," [%d] \0030,14 DCC \003 %s",index,message); echo(temp,pathname,1); } // Generic Network Handling Function for DCC's. If something happens on a // socket, this gets called. void tdcc::handle(int mask) { int numbytes; char temp[TEMPLEN]; //if(networklock) return; //networklock=1; //printf("Hi, here I am\n"); switch(type) { case DCCCHAT: if(listening) { if(mask & TCL_READABLE) { do_accept(); } } else if(connected) { if(mask & TCL_READABLE) { if((numbytes=recv(sockfd,temp,TEMPLEN-1,0))==-1) { perror("Receiving"); disconnect(); } else { if(numbytes) { temp[numbytes]=0; if((strlen(buffer)+strlen(temp))dcc->pathname,1); } windowexists=1; windowp->dcc->connecting=0; windowp->dcc->connected=0; windowp->dcc->listening=0; errortest=0; strcpy(windowp->dcc->ip,theip); windowp->dcc->port=theport; if((windowp->dcc->sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) { windowp->dcc->perror("Getting Socket File Descriptor for DCC"); errortest=1; return; } fcntl(windowp->dcc->sockfd, F_SETFL, O_NONBLOCK); addr.sin_family=AF_INET; addr.sin_port=htons(windowp->dcc->port); addr.sin_addr.s_addr=inet_addr(windowp->dcc->ip); bzero(&(addr.sin_zero),8); sprintf(assemble," \0030,14 DCC \003 Attempting connection to %s",windowp->dcc->ip); echo(assemble,windowp->dcc->pathname,1); windowp->dcc->connecting=1; if(connect(windowp->dcc->sockfd,(struct sockaddr *)&addr,sizeof(struct sockaddr))) { // We got an error. If it's just EINPROGRESS keep going, otherwise error. if(errno!=EINPROGRESS) { windowp->dcc->perror("Connecting [Immediate]"); windowp->dcc->disconnect(); errortest=1; return; } Tcl_CreateFileHandler(windowp->dcc->sockfd,TCL_WRITABLE,handle_networking,windowp->dcc); } else { windowp->dcc->connected=1; windowp->dcc->connecting=0; echo(" \0030,14 DCC \003 Connected.",windowp->dcc->pathname,1); Tcl_CreateFileHandler(windowp->dcc->sockfd,TCL_READABLE,handle_networking,windowp->dcc); } } } if(!windowexists) { connecting=0; connected=0; listening=0; ip[0]=0; errortest=0; type=DCCCHAT; filefd=0; setnick(thenick); strcpy(ip,theip); port=theport; server=serverp; sprintf(pathname,".chat%d",chatnum); strcpy(window.pathname,pathname); window.server=serverp; window.dcc=this; window.title="QuIRC - "; window.title+=window.name; n=windows.insert_ascending(window); TT_EvalF(TT_ARGS,"Init_Window .chat%d %q %d chat %d",chatnum,window.name,n,serverp->index); TT_EvalF(TT_ARGS,"totop %d",n); chatnum++; if(connected) { echo(" \0030,5 ERROR \003 Already Connected",pathname,1); errortest=1; return; } if(connecting) { echo(" \0030,5 ERROR \003 We're in the middle of connecting, hold your horses!\n",pathname,1); errortest=1; return; } if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) { perror("Getting Socket File Descriptor for DCC"); errortest=1; return; } fcntl(sockfd, F_SETFL, O_NONBLOCK); addr.sin_family=AF_INET; addr.sin_port=htons(port); addr.sin_addr.s_addr=inet_addr(ip); bzero(&(addr.sin_zero),8); sprintf(assemble," \0030,14 DCC \003 Attempting connection to %s",ip); echo(assemble,pathname,1); connecting=1; if(connect(sockfd,(struct sockaddr *)&addr,sizeof(struct sockaddr))) { // We got an error. If it's just EINPROGRESS keep going, otherwise error. if(errno!=EINPROGRESS) { perror("Connecting [Immediate]"); disconnect(); errortest=1; return; } Tcl_CreateFileHandler(sockfd,TCL_WRITABLE,handle_networking,this); } else { connected=1; connecting=0; echo(" \0030,14 DCC \003 Connected.",pathname,1); Tcl_CreateFileHandler(sockfd,TCL_READABLE,handle_networking,this); } memset(buffer,0,BUFLEN); } } tdcc::tdcc(tserver *serverp, const char *thenick, char *theip, int theport, char *thefile, int thesize, int dccflags, const char *renamedfile) { // DCC SEND ACCEPT twindow window; struct sockaddr_in addr; char assemble[TEMPLEN]; tdccentry dccentry; int n; nick = mystrdup(thenick); sprintf(window.pathname,".files%d",serverp->index); if(!windows.find(window)) { strcat(window.name,"DCC Files"); window.server=serverp; window.dcc=0; window.title="QuIRC - DCC Files"; n=windows.insert_ascending(window); TT_EvalF(TT_ARGS,"Init_Window %q %q %d files %d",window.pathname,window.name,n,serverp->index); TT_EvalF(TT_ARGS,"pack forget %s.text %s.entry %s.text_vscroll",window.pathname,window.pathname,window.pathname); TT_EvalF(TT_ARGS,"grid columnconfigure %s 0 -weight 1",window.pathname); //TT_EvalF(TT_ARGS,"grid rowconfigure %s 0 -weight 1",window.pathname); TT_EvalF(TT_ARGS,"grid rowconfigure %s 1 -weight 1",window.pathname); TT_EvalF(TT_ARGS,"grid [listbox %s.list -yscroll \"%s.list_vscroll set\" -height 11 -exportselection no] -column 0 -row 0 -sticky new",window.pathname,window.pathname,window.pathname); TT_EvalF(TT_ARGS,"grid [scrollbar %s.list_vscroll -command \"%s.list yview\"] -column 1 -row 0 -sticky ns",window.pathname,window.pathname,window.pathname,window.pathname); TT_EvalF(TT_ARGS,"grid %s.text -column 0 -row 1 -sticky nsew",window.pathname); TT_EvalF(TT_ARGS,"grid %s.text_vscroll -column 1 -row 1 -sticky ns",window.pathname); TT_EvalF(TT_ARGS,"grid %s.entry -column 0 -row 2 -columnspan 2 -sticky ew",window.pathname); TT_EvalF(TT_ARGS,"%s.list configure -foreground $::dynamic::theme_filelist_foreground -background $::dynamic::theme_filelist_background -font $::dynamic::theme_filelist_font",window.pathname); TT_EvalF(TT_ARGS,"bind %s.list {::template::killdcc [currentindex] [%s.list nearest %y]}",window.pathname,window.pathname); echo(" \0030,14 DCC \003 Right click on files in the list to remove them.",window.pathname,0); TT_EvalF(TT_ARGS,"totop %d",n); //serverp->dcclist.insert_end(dccentry); //TT_EvalF(TT_ARGS,"%s.list insert 0 [::format_dcc_status Index Status]",window.pathname); } index=filenum++; strcpy(pathname,window.pathname); written=0; connecting=0; connected=0; listening=0; ip[0]=0; errortest=0; type=DCCFILEGET; filefd=0; size=thesize; checkflags=dccflags; struct timeval tv; struct timezone tz; tz.tz_minuteswest=0; tz.tz_dsttime=0; if(gettimeofday(&tv,&tz)) { perror("Call to gettimeofday()"); errortest=1; return; } dccseconds=tv.tv_sec; dccmilliseconds=tv.tv_usec; dccentry.dcc=this; entryindex=serverp->dcclist.insert_end(dccentry); //TT_EvalF(TT_ARGS,"%s.list insert %d [::format_dcc_status %d \"\"]",window.pathname,entryindex,index); TT_EvalF(TT_ARGS,"%s.list insert %d \" \\[%d]\"",window.pathname,entryindex,index); strcpy(destfile,TT_Str(TT_ARGS,"set ::dynamic::dcc_directory")); strcat(destfile,"/"); strcat(destfile,renamedfile); strcpy(file,thefile); strcpy(ip,theip); port=theport; server=serverp; if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) { perror("Getting Socket File Descriptor for DCC"); return; } fcntl(sockfd, F_SETFL, O_NONBLOCK); addr.sin_family=AF_INET; addr.sin_port=htons(port); addr.sin_addr.s_addr=inet_addr(ip); bzero(&(addr.sin_zero),8); sprintf(assemble," [%d] \0030,14 DCC \003 Attempting connection to %s",index,ip); echo(assemble,pathname,1); connecting=1; if(connect(sockfd,(struct sockaddr *)&addr,sizeof(struct sockaddr))) { // We got an error. If it's just EINPROGRESS keep going, otherwise error. if(errno!=EINPROGRESS) { perror("Connecting [Immediate]"); disconnect(); errortest=1; return; } Tcl_CreateFileHandler(sockfd,TCL_WRITABLE,handle_networking,this); } else { connected=1; connecting=0; sprintf(assemble," [%d] \0030,14 DCC \003 Connected.",index); echo(assemble,pathname,1); Tcl_CreateFileHandler(sockfd,TCL_READABLE|TCL_WRITABLE,handle_networking,this); } memset(buffer,0,BUFLEN); } tdcc::tdcc(tserver *serverp, const char *thenick) { // DCC CHAT SEND char temp[TEMPLEN]; twindow window; twindow *windowp; int n; struct sockaddr_in my_addr; socklen_t my_addr_len=sizeof(struct sockaddr); nick = mystrdup(thenick); if(!strcasecmp(thenick,serverp->getmynick())) { echo(" \0030,5 ERROR \003 You cannot DCC Chat yourself.",serverp->pathname,1); return; } strcpy(window.name,"="); strcat(window.name,nick); windows.init_trav(); while((windowp=windows.trav())) { if(!strcasecmp(windowp->name,window.name)&&(windowp->server==serverp)) { if(windowp->dcc->sockfd&&(windowp->dcc->connected||windowp->dcc->listening||windowp->dcc->connecting)) { close(windowp->dcc->sockfd); echo(" \0030,14 DCC \003 Disconnected.",windowp->dcc->pathname,1); } windowp->dcc->connecting=0; windowp->dcc->connected=0; windowp->dcc->listening=1; errortest=0; if((windowp->dcc->sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) { windowp->dcc->perror("Getting Socket File Descriptor for DCC"); errortest=1; return; } my_addr.sin_family=AF_INET; my_addr.sin_port=0; my_addr.sin_addr.s_addr=INADDR_ANY; bzero(&(my_addr.sin_zero),8); if(bind(windowp->dcc->sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))==-1) { windowp->dcc->perror("Binding DCC Socket"); errortest=1; return; } if(getsockname(windowp->dcc->sockfd,(struct sockaddr *)&my_addr,&my_addr_len)==-1) { windowp->dcc->perror("Getting DCC Socket Name"); errortest=1; return; } windowp->dcc->port=ntohs(my_addr.sin_port); if(listen(windowp->dcc->sockfd,1)==-1) { windowp->dcc->perror("Listening for DCC Connection"); errortest=1; return; } Tcl_CreateFileHandler(windowp->dcc->sockfd,TCL_READABLE,handle_networking,windowp->dcc); if(strlen(TT_Str(TT_ARGS,"set ::dynamic::dcc_localip"))) { sprintf(temp,"PRIVMSG %s :\001DCC CHAT chat %u %d\001",thenick,htonl(inet_addr(TT_Str(TT_ARGS,"set ::dynamic::dcc_localip"))),windowp->dcc->port); } else { sprintf(temp,"PRIVMSG %s :\001DCC CHAT chat %u %d\001",thenick,htonl(inet_addr(serverp->localip)),windowp->dcc->port); } // DEBUG //TT_EvalF(TT_ARGS,".raw.text insert end \"Command (dcc.cc:465): %q\\n\"",temp); windowp->dcc->server->senddata(temp); return; } } connecting=0; connected=0; listening=1; ip[0]=0; errortest=0; type=DCCCHAT; filefd=0; if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) { serverp->perror("Getting Socket File Descriptor for DCC"); errortest=1; return; } my_addr.sin_family=AF_INET; my_addr.sin_port=0; my_addr.sin_addr.s_addr=INADDR_ANY; bzero(&(my_addr.sin_zero),8); if(bind(sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))==-1) { serverp->perror("Binding DCC Socket"); errortest=1; return; } if(getsockname(sockfd,(struct sockaddr *)&my_addr,&my_addr_len)==-1) { serverp->perror("Getting DCC Socket Name"); errortest=1; return; } port=ntohs(my_addr.sin_port); // Change to 0? if(listen(sockfd,1)==-1) { serverp->perror("Listening for DCC Connection"); errortest=1; return; } memset(buffer,0,BUFLEN); Tcl_CreateFileHandler(sockfd,TCL_READABLE,handle_networking,this); sprintf(temp,"PRIVMSG %s :\001DCC CHAT chat %u %d\001",thenick,htonl(inet_addr(serverp->localip)),port); // DEBUG //TT_EvalF(TT_ARGS,".raw.text insert end \"Command (dcc.cc:526): %q\\n\"",temp); serverp->senddata(temp); server=serverp; sprintf(pathname,".chat%d",chatnum); strcpy(window.pathname,pathname); window.server=serverp; window.dcc=this; window.title="QuIRC - "; window.title+=window.name; n=windows.insert_ascending(window); TT_EvalF(TT_ARGS,"Init_Window .chat%d %q %d chat %d",chatnum,window.name,n,serverp->index); TT_EvalF(TT_ARGS,"totop %d",n); chatnum++; } tdcc::tdcc(tserver *serverp, const char *thenick, const char *thefile) { // DCC SEND SEND char temp[TEMPLEN]; twindow window; //twindow *windowp; int n; struct sockaddr_in my_addr; socklen_t my_addr_len=sizeof(struct sockaddr); //int windowexists=0; char *p; FILE *myfile; tdccentry dccentry; nick = mystrdup(thenick); strcpy(file,thefile); if((p=rindex(file,'/'))) { strcpy(destfile,++p); } else { strcpy(destfile,thefile); } while((p=strstr(destfile," "))) { *p='_'; } sprintf(window.pathname,".files%d",serverp->index); if(!windows.find(window)) { strcat(window.name,"DCC Files"); window.server=serverp; window.dcc=0; window.title="QuIRC - DCC Files"; n=windows.insert_ascending(window); TT_EvalF(TT_ARGS,"Init_Window %q %q %d files %d",window.pathname,window.name,n,serverp->index); TT_EvalF(TT_ARGS,"pack forget %s.text %s.entry %s.text_vscroll",window.pathname,window.pathname,window.pathname); TT_EvalF(TT_ARGS,"grid columnconfigure %s 0 -weight 1",window.pathname); //TT_EvalF(TT_ARGS,"grid rowconfigure %s 0 -weight 1",window.pathname); TT_EvalF(TT_ARGS,"grid rowconfigure %s 1 -weight 1",window.pathname); TT_EvalF(TT_ARGS,"grid [listbox %s.list -yscroll \"%s.list_vscroll set\" -height 11 -exportselection no] -column 0 -row 0 -sticky new",window.pathname,window.pathname,window.pathname); TT_EvalF(TT_ARGS,"grid [scrollbar %s.list_vscroll -command \"%s.list yview\"] -column 1 -row 0 -sticky ns",window.pathname,window.pathname,window.pathname,window.pathname); TT_EvalF(TT_ARGS,"grid %s.text -column 0 -row 1 -sticky nsew",window.pathname); TT_EvalF(TT_ARGS,"grid %s.text_vscroll -column 1 -row 1 -sticky ns",window.pathname); TT_EvalF(TT_ARGS,"grid %s.entry -column 0 -row 2 -columnspan 2 -sticky ew",window.pathname); TT_EvalF(TT_ARGS,"%s.list configure -foreground $::dynamic::theme_filelist_foreground -background $::dynamic::theme_filelist_background -font $::dynamic::theme_filelist_font",window.pathname); TT_EvalF(TT_ARGS,"bind %s.list {::template::killdcc [currentindex] [%s.list nearest %y]}",window.pathname,window.pathname); echo(" \0030,14 DCC \003 Right click on files in the list to remove them.",window.pathname,0); TT_EvalF(TT_ARGS,"totop %d",n); //serverp->dcclist.insert_end(dccentry); //TT_EvalF(TT_ARGS,"%s.list insert 0 [::format_dcc_status Index Status]",window.pathname); } index=filenum++; strcpy(pathname,window.pathname); connecting=0; connected=0; listening=1; ip[0]=0; errortest=0; transmitted=0; filefd=0; server=serverp; struct timeval tv; struct timezone tz; tz.tz_minuteswest=0; tz.tz_dsttime=0; if(gettimeofday(&tv,&tz)) { perror("Call to gettimeofday()"); errortest=1; return; } dccseconds=tv.tv_sec; dccmilliseconds=tv.tv_usec; if((myfile=fopen(file,"rb"))) { fseek(myfile,0,SEEK_END); size=ftell(myfile); fclose(myfile); } type=DCCFILESEND; if((filefd=open(file,O_RDONLY))==-1) { perror("Opening Given File"); errortest=1; return; } if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) { perror("Getting Socket File Descriptor"); errortest=1; return; } fcntl(sockfd, F_SETFL, O_NONBLOCK); my_addr.sin_family=AF_INET; my_addr.sin_port=0; my_addr.sin_addr.s_addr=INADDR_ANY; bzero(&(my_addr.sin_zero),8); if(bind(sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))==-1) { perror("Binding Socket"); errortest=1; return; } if(getsockname(sockfd,(struct sockaddr *)&my_addr,&my_addr_len)==-1) { perror("Getting Socket Name"); errortest=1; return; } port=ntohs(my_addr.sin_port); // Change to 0? if(listen(sockfd,1)==-1) { perror("Listening for Connection"); errortest=1; return; } dccentry.dcc=this; entryindex=serverp->dcclist.insert_end(dccentry); //TT_EvalF(TT_ARGS,"%s.list insert %d [::format_dcc_status %d \"\"]",window.pathname,entryindex,index); TT_EvalF(TT_ARGS,"%s.list insert %d \" \\[%d]\"",window.pathname,entryindex,index); memset(buffer,0,BUFLEN); Tcl_CreateFileHandler(sockfd,TCL_READABLE,handle_networking,this); if(strlen(TT_Str(TT_ARGS,"set ::dynamic::dcc_localip"))) { sprintf(temp,"PRIVMSG %s :\001DCC SEND %s %u %d %ld\001",thenick,destfile,htonl(inet_addr(TT_Str(TT_ARGS,"set ::dynamic::dcc_localip"))),port,size); } else { sprintf(temp,"PRIVMSG %s :\001DCC SEND %s %u %d %ld\001",thenick,destfile,htonl(inet_addr(serverp->localip)),port,size); } // DEBUG //TT_EvalF(TT_ARGS,".raw.text insert end \"Command (dcc.cc:686): %q\\n\"",temp); serverp->senddata(temp); if(!errortest) { sprintf(temp,"Attempting to Send %s to %s",file,nick); filemessage(temp); } } int tdcc::senddata(const char *message) { char *temp=strmem(message,1); if(connected) { strcat(temp,"\n"); if(send(sockfd,temp,(signed)strlen(temp),0)!=(signed)strlen(temp)) { perror("Sending"); disconnect(); return 1; } TT_EvalF(TT_ARGS,"if { $::dynamic::do_rawview } \" .raw.text insert end \\\"DCC Command: [escape %q]\\n\\\"\"",message); return 0; } free(temp); return 1; } void tdcc::sendchunk() { Tcl_CreateFileHandler(sockfd,TCL_READABLE|TCL_WRITABLE,handle_networking,this); } int tdcc::handle_incoming() { // Returns 1 if disconnect was performed. if(type==DCCFILESEND) { ssize_t numbytes; char assemble[TEMPLEN]; unsigned int buffer; numbytes=read(sockfd,&buffer,4); acknowledged=ntohl(buffer); if(numbytes) { if(numbytes>0) { struct timeval tv; struct timezone tz; long checktime; tz.tz_minuteswest=0; tz.tz_dsttime=0; if(gettimeofday(&tv,&tz)) { perror("Call to gettimeofday()"); return 1; } checktime=(tv.tv_sec-dccseconds)*1000+(tv.tv_usec-dccmilliseconds)/1000; if(checktime>=TT_Int(TT_ARGS,"set ::dynamic::dcc_statuswait")) { dccmilliseconds=tv.tv_usec; dccseconds=tv.tv_sec; tdccentry dccentry; dccentry.dcc=this; entryindex=server->dcclist.find(dccentry)->index; if(!(server->script("event_dcc_sendstatus","d q q q d d d d",entryindex,nick,file,destfile,acknowledged,transmitted,size,index)&6)) { sprintf(assemble,"%3d%%",(int)(acknowledged/(float)size*100)); echo(assemble,pathname,1); } } if(acknowledged>=transmitted) sendchunk(); } else { perror("Getting Data"); disconnect(); return 1; } } else { disconnect(); return 1; } if(acknowledged==size) { disconnect(); return 1; } } if(type==DCCFILEGET) { ssize_t numbytes; char buffer[TEMPLEN]; ssize_t checkbytes; numbytes=read(sockfd,buffer,TEMPLEN); if(numbytes) { if(numbytes>0) { if(write(filefd,buffer,numbytes)!=numbytes) { perror("Writing to File"); disconnect(); return 1; } else { written+=numbytes; checkbytes=htonl(written); if(write(sockfd,(char *)&checkbytes,4)!=4) { perror("Sending Confirmation"); disconnect(); return 1; } else { struct timeval tv; struct timezone tz; long checktime; tz.tz_minuteswest=0; tz.tz_dsttime=0; if(gettimeofday(&tv,&tz)) { perror("Call to gettimeofday()"); return 1; } checktime=(tv.tv_sec-dccseconds)*1000+(tv.tv_usec-dccmilliseconds)/1000; if(checktime>=TT_Int(TT_ARGS,"set ::dynamic::dcc_statuswait")) { dccmilliseconds=tv.tv_usec; dccseconds=tv.tv_sec; tdccentry dccentry; dccentry.dcc=this; entryindex=server->dcclist.find(dccentry)->index; if(!(server->script("event_dcc_getstatus","d q q q d d d",entryindex,nick,destfile,file,written,size,index)&6)) { char assemble[TEMPLEN]; sprintf(assemble," %d",written); echo(assemble,pathname,1); } } } } } else { perror("Getting Data"); disconnect(); return 1; } } else { disconnect(); return 1; } } return 0; } void tdcc::usedata() { char *thisline; char *position; char temp[TEMPLEN]; while((position=strstr(buffer,"\n"))) { *position=0; thisline=strmem(buffer,0); if(thisline[strlen(thisline)-1]=='\r') thisline[strlen(thisline)-1]=0; strcpy(buffer,position+1); if(!(server->script("event_dcc_text","q q",nick,thisline)&2)) { sprintf(temp,"<%s> %s",nick,thisline); echo(temp,pathname,1); } free(thisline); } } void tdcc::complete_connect() { socklen_t optlen; int optval; optlen=sizeof(optval); getsockopt(sockfd,SOL_SOCKET,SO_ERROR,(void *)&optval,&optlen); if(optval) { perror("Connecting",optval); disconnect(); } else { connected=1; connecting=0; if(type==DCCFILESEND) { tdccentry dccentry; dccentry.dcc=this; entryindex=server->dcclist.find(dccentry)->index; if(!(server->script("event_dcc_connect","q q q d q q q d d d",pathname,nick,ip,port,"filesend",file,destfile,size,index,entryindex))&6) { echo(" \0030,14 DCC \003 Connected.",pathname,1); } // CHANGE Tcl_CreateFileHandler(sockfd,TCL_READABLE|TCL_WRITABLE,handle_networking,this); } if(type==DCCFILEGET) { tdccentry dccentry; dccentry.dcc=this; entryindex=server->dcclist.find(dccentry)->index; if(!(server->script("event_dcc_connect","q q q d q q q d d d",pathname,nick,ip,port,"fileget",destfile,file,size,index,entryindex))&6) { echo(" \0030,14 DCC \003 Connected.",pathname,1); } if(checkflags & DCC_OVERWRITE) { if((filefd=open(destfile,O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH))==-1) { perror("Opening for Writing"); disconnect(); return; } } else { if((filefd=open(destfile,O_WRONLY|O_CREAT|O_EXCL,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH))==-1) { perror("Opening for Writing"); disconnect(); return; } } timestarted=time(0); // CHANGE Tcl_CreateFileHandler(sockfd,TCL_READABLE,handle_networking,this); } if(type==DCCCHAT) { if(!(server->script("event_dcc_connect","q q q d q",pathname,nick,ip,port,"chat"))&6) { echo(" \0030,14 DCC \003 Connected.",pathname,1); } // CHANGE Tcl_CreateFileHandler(sockfd,TCL_READABLE,handle_networking,this); } } } void tdcc::do_accept() { struct sockaddr_in addr; socklen_t addrlength; int tempfd; addrlength=sizeof(struct sockaddr); listening=0; if((tempfd=accept(sockfd,(struct sockaddr *)&addr,&addrlength))==-1) { perror("Accepting DCC Connection"); Tcl_DeleteFileHandler(sockfd); close(sockfd); } else { connected=1; if(type==DCCFILESEND) { tdccentry dccentry; dccentry.dcc=this; entryindex=server->dcclist.find(dccentry)->index; if(!(server->script("event_dcc_connect","q q q d q q q d d d",pathname,nick,ip,port,"filesend",file,destfile,size,index,entryindex))&6) { echo(" \0030,14 DCC \003 Connected.",pathname,1); } // CHANGE Tcl_CreateFileHandler(tempfd,TCL_READABLE|TCL_WRITABLE,handle_networking,this); } if(type==DCCCHAT) { if(!(server->script("event_dcc_connect","q q q d q",pathname,nick,ip,port,"chat"))&6) { echo(" \0030,14 DCC \003 Connected.",pathname,1); } // CHANGE Tcl_CreateFileHandler(tempfd,TCL_READABLE,handle_networking,this); } Tcl_DeleteFileHandler(sockfd); close(sockfd); sockfd=tempfd; if(type==DCCFILESEND) { timestarted=time(0); sendchunk(); } } } void tdcc::handle_outgoing(void) { int packetsize=TT_Int(TT_ARGS,"set ::dynamic::dcc_packetsize"); char readbuffer[packetsize]; ssize_t numbytes; numbytes=read(filefd,readbuffer,packetsize); if(numbytes) { if(numbytes>0) { if(send(sockfd,readbuffer,numbytes,0)!=numbytes) { perror("Sending"); disconnect(); } transmitted+=numbytes; } else { perror("Reading Data File"); } } Tcl_CreateFileHandler(sockfd,TCL_READABLE,handle_networking,this); } void killdcc(ClientData clientData) { delete (class tdcc *)clientData; } int tdcc::disconnect(void) { char temp[100]; if(listening||connected||connecting) { // Error check close if(sockfd) close(sockfd); if(filefd) close(filefd); if(type==DCCFILESEND||type==DCCFILEGET) { sprintf(temp," [%d] \0030,14 DCC \003 Disconnected.",index); echo(temp,pathname,1); } else { echo(" \0030,14 DCC \003 Disconnected.",pathname,1); } listening=0; connected=0; connecting=0; } if(type==DCCFILESEND||type==DCCFILEGET) { tdccentry dccentry; dccentry.dcc=this; entryindex=server->dcclist.deleteitem(dccentry); TT_EvalF(TT_ARGS,"%s.list delete %d %d",pathname,entryindex,entryindex); sprintf(temp," [%d] \0030,14 DCC \003 Destroyed.",index); echo(temp,pathname,1); Tcl_CreateTimerHandler(300,killdcc,this); } memset(buffer,0,BUFLEN); Tcl_DeleteFileHandler(sockfd); return 0; }