#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <strings.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <time.h>
#include <sys/time.h>
#ifdef DMALLOC
#include <dmalloc.h>
#endif
#ifdef SOCKS
#include <socks.h>
#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))<BUFLEN) {
strcat(buffer,temp);
usedata();
} else {
echo("Buffer Overrun in DCCCHAT (Please contact author at quirc@patearl.net)",".main",1);
}
} else {
disconnect();
}
}
}
} else if (connecting) {
if(mask & TCL_WRITABLE) {
complete_connect();
}
}
break;
case DCCFILEGET:
if(connected) {
if(mask & TCL_READABLE) {
handle_incoming();
}
} else if (connecting) {
if(mask & TCL_WRITABLE) {
complete_connect();
}
}
break;
case DCCFILESEND:
if(listening) {
if(mask & TCL_READABLE) {
do_accept();
}
} else if(connected) {
int incoming_result=0;
if(mask & TCL_READABLE) {
//printf("1 - %d\n",time());
incoming_result=handle_incoming();
//printf("2\n");
}
if(!incoming_result && (mask & TCL_WRITABLE)) {
//printf("3\n");
handle_outgoing();
//printf("4\n");
}
} else {
fprintf(stderr,"DCC file sends shouldn't be connecting, they should be accepting.\n");
exit(1);
}
// else if (connecting) {
//if(mask & TCL_WRITABLE) {
//complete_connect();
//}
//}
break;
default:
fprintf(stderr,"Something bad has happened, there wasn't a valid type for the dcc.\n");
exit(1);
}
//networklock=0;
}
int tdcc::getflags() {
return flags;
}
int tdcc::getsockfd() {
return sockfd;
}
tdcc::tdcc(tserver *serverp, const char *thenick, char *theip, int theport) {
// DCC CHAT ACCEPT
twindow window;
twindow *windowp;
int n;
struct sockaddr_in addr;
int windowexists=0;
char assemble[TEMPLEN];
nick = mystrdup("");
strcpy(window.name,"=");
strcat(window.name,thenick);
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);
}
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 <Button-3> {::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 <Button-3> {::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;
}
syntax highlighted by Code2HTML, v. 0.9.1