Hello!
I'm making an IRC Client with DCC Capabilities.
The DCC Specifications say this about receiving files:
The recipient should acknowledge each packet by transmitting
the total number of bytes received as an unsigned, 4 byte
integer in network byte order.
In do this with the following code:
typedef unsigned int guint32;
guint32 pos = htonl (count & 0xffffffff);
send(sockfd,(char*) &pos,4,0);
This is the same code that is in the XChat source code.
Now this code works fine with the xchat client itself.
But those 3 lines of code make my own client fail in sending files to another instance of my client.
When I include those 3 lines and I run 2 instances of my program and then try to send a file to each other, the program sends 10 MB of the file and then just stops.
This is my send code:
void listenSocket (void *arg,void *inputUser,void *inputFileName,void *inputFileLoc)
{
struct sockaddr_storage their_addr;
struct addrinfo hints, *servinfo;
struct in_addr addr;
socklen_t addr_size;
int len, bytes_sent, bytes_received, fdmax, new_fd, nbytes, j, i,myRandPort=0;
int sockfdIRCSocket = (int)arg, sockfd ,bindfd , listenfd;
unsigned long long int countSentBytes=0;
char *sendToUser = (char*)inputUser, *fileName = (char*)inputFileName, *fileLoc = (char*)inputFileLoc;
char strSizeFile[50], buffer[5120], hostip[30], read[500], sendDCC[500], decResult[50], hostname[80], *pch;
char buf[500], remoteIP[INET6_ADDRSTRLEN], MYPORT[6]="\0",bufferke[4];
long sizeFile;
bool bolSendFile = false;
fd_set master; // master file descriptor list
fd_set read_fds;
strSizeFile[0] = '\0';
decResult[0]= '\0';
hostip[0]= '\0';
srand(time(NULL));
myRandPort=getRand(49152,65535);
sprintf(MYPORT,"%d",myRandPort);
//Socket Stuff
WSADATA wsaData;
if (WSAStartup(MAKEWORD(1,1), &wsaData) != 0) {
Log("WSAStartup","WSAStartup failed");
closesocket(1);
}
//File thats needs to be sended
FILE *fp;
//Read + Open File
if((fp = fopen(fileLoc, "rb+"))==NULL) {
printf(":Cannot open file, please pick another.\n");
Log("DCC File Send","Cannot open file, please pick another.");
return;
}
//Get Filesize
fseek(fp, 0,SEEK_END);
sizeFile = ftell(fp);
ltoa(sizeFile,strSizeFile,10);
fseek(fp, 0,SEEK_SET);
//GET IP
if (gethostname(hostname, sizeof(hostname)) == SOCKET_ERROR) {
Log("DCC Send Host","No Host Found");
}
struct hostent *phe = gethostbyname(hostname);
memcpy(&addr, phe->h_addr_list[1], sizeof(struct in_addr));
sprintf(hostip,"%s",inet_ntoa(addr));
//Convert IP to Decimal notation
sprintf(decResult,"%u", addr);
sprintf(decResult,"%u", htonl(atoi(decResult)));
// \001DCC SEND test.txt <decimal> 9999 70\001
sendDCC[0] = '\0';
strcat(sendDCC,"PRIVMSG ");
strcat(sendDCC, sendToUser);
strcat(sendDCC," :\001DCC SEND ");
strcat(sendDCC, fileName);
strcat(sendDCC," ");
strcat(sendDCC, decResult);
strcat(sendDCC," ");
strcat(sendDCC, MYPORT);
strcat(sendDCC, " ");
strcat(sendDCC, strSizeFile);
strcat(sendDCC, "\001\n");
//Socket Stuff
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever
hints.ai_socktype = SOCK_STREAM; //TCP
hints.ai_flags = AI_PASSIVE; // fill in my IP for me
//AddrInfo
getaddrinfo(hostip,MYPORT, &hints, &servinfo);
//Create a socket
sockfd = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol);
if(sockfd > 0)
{
//printf("\n:Socket(%i): OK\n\n",sockfd);
Log("DCC Send Create Socket","Sockted created");
}
else
{
//wprintf(L"### Bind failed with error: %ld\n\n", WSAGetLastError());
Log("DCC Send Create Socket","Sockted failed");
}
//Bind
bindfd = bind(sockfd, servinfo->ai_addr, servinfo->ai_addrlen);
if(bindfd == 0)
{
//printf(":Bind: OK\n\n",bindfd);
Log("DCC Send Bind","Bind ok");
}
else
{
//wprintf(L"### Bind failed with error: %ld\n\n", WSAGetLastError());
Log("DCC Send Bind","Bind failed");
}
//Listen
for(;;){
listenfd = listen(sockfd, 10);
if(listenfd == 0)
{
//printf(":Listening on port %s...\n\n",MYPORT);
Log("Port listening",MYPORT);
}
else
{
//wprintf(L"### Listen failed with error: %ld\n\n", WSAGetLastError());
Log("DCC Send Listen","Listen Failed");
}
FD_ZERO(&master);
FD_ZERO(&read_fds);
FD_SET(sockfd, &master);
fdmax = sockfd;
//sendToServer("PRIVMSG bigvince :\001DCC SEND test.txt 127.0.0.1 9999 70\001\n",(void *)sockfdIRCSocket);
sendToServer(sendDCC,(void *)sockfdIRCSocket);
int bytes_rex = 0;
// main loop
for(;;) {
read_fds = master; // copy it
if (select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1) {
//wprintf(L"### Select failed with error: %ld\n\n", WSAGetLastError());
Log("DCC Send Select","Select failed");
closesocket(4);
}
// run through the existing connections looking for data to read
for(i = 0; i <= fdmax; i++) {
if (FD_ISSET(i, &read_fds)) { // we got one!!
if (i == sockfd) {
// handle new connections
addr_size = sizeof their_addr;
new_fd = accept(sockfd,(struct sockaddr *)&their_addr,&addr_size);
//printf("accept");
if (new_fd == -1) {
//wprintf(L"### Accept failed with error: %ld\n\n", WSAGetLastError());
Log("DCC Send Accept","Accept failed");
}
else
{
Log("DCC Send Accept","Accept all good");
FD_SET(new_fd, &master); // add to master set
if (new_fd > fdmax)
{ // keep track of the max
fdmax = new_fd;
}
//printf(":New connection from %s on socket %d\n\n", inet_ntop(their_addr.ss_family,&their_addr,remoteIP, INET6_ADDRSTRLEN),new_fd);
Log("DCC Send New Connection", (char *)inet_ntop(their_addr.ss_family,&their_addr,remoteIP, INET6_ADDRSTRLEN));
if (atoi(strSizeFile)<sizeof(buffer))
{
//Read file into buffer
len = fread(&buffer,atoi(strSizeFile),1,fp);
//Send buffer into network
bytes_sent = send(new_fd, buffer, atoi(strSizeFile), 0);
if (bytes_sent > 0)
{
printf("\n:>Sending file\n");
}
else if (bytes_sent == -1)
{
wprintf(L"### Send failed with error: %ld\n\n", WSAGetLastError());
//Log("DCC Send Filebytes","Send failed");
fclose(fp);
return;
}
}
else
{
do {
//Read file into buffer
fread(&buffer,sizeof(buffer),1,fp);
//Send buffer into network
bytes_sent = send(new_fd, buffer, sizeof(buffer), 0);
if (bytes_sent > 0)
{
countSentBytes = countSentBytes + bytes_sent;
if (bolSendFile == false)
{
printf("\n:>Sending file\n");
bolSendFile = true;
}
printf(".");
}
else if (bytes_sent == -1)
{
wprintf(L"### Send failed with error: %ld\n\n", WSAGetLastError());
//Log("DCC Send Filebytes","Send failed");
fclose(fp);
return;
}
else
{
printf("lala");
}
}while(countSentBytes < atoi(strSizeFile));
}
if(countSentBytes = atoi(strSizeFile) )
{
printf("\n:>File transfer complete \n\n");
bolSendFile = false;
}
fclose(fp);
}
}
}
}
}
}
}
And my Receive Code:
struct sockaddr_storage their_addr;
struct addrinfo hints, *servinfo, *p;
struct in_addr addr;
socklen_t addr_size;
int sockfd ,bindfd , listenfd;
char buffer[1024], filePath[50];
char s[INET6_ADDRSTRLEN], *dotted_quad;
int numbytes=0;
unsigned long long int count =0;
bool bolRecvFile=false;
FILE *fp;
//File Location
filePath[0] = '\0';
strcat(filePath,"C:\\");
strcat(filePath,file);
strcat(filePath,"\0");
//Socket Stuff
WSADATA wsaData;
if (WSAStartup(MAKEWORD(1,1), &wsaData) != 0) {
Log("WSAStartup","WSAStartup failed");
closesocket(1);
}
//Socket Stuff
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever
hints.ai_socktype = SOCK_STREAM; //TCP
hints.ai_flags = AI_PASSIVE; // fill in my IP for me
//Convert Decimal Notation to Dotted Decimal Notation
unsigned long numeric_ip = (unsigned) strtoul(ip,NULL,10);
numeric_ip = htonl(numeric_ip); // flip the byte order
memcpy(&addr, &numeric_ip, sizeof(numeric_ip));
dotted_quad = inet_ntoa(addr);
getaddrinfo(dotted_quad, port, &hints, &servinfo);
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,p->ai_protocol)) == -1) {
//wprintf(L"### Socket failed with error: %ld\n\n", WSAGetLastError());
Log("Socket","Sockted failed with error");
}
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
//wprintf(L"\n### Connect failed with error: %ld\n\n", WSAGetLastError());
Log("Connect","Connect failed with error");
closesocket(sockfd);
continue;
}
break;
}
if (p == NULL) {
printf("Failed to connect\n");
}
if((fp=fopen(filePath, "wb"))==NULL) {
printf(":Cannot open file, please pick another.\n");
Log("DCC File Receive","Cannot open file, please pick another.");
return;
}
int bytes_sent=0;
do {
//Receiving From Socket
numbytes = recv(sockfd, buffer, sizeof(buffer), 0);
if(numbytes>4)
{
//Counting Bytes Received
count = count + numbytes;
if (bolRecvFile == false)
{
printf("\n:>Receiving File\n", file);
bolRecvFile = true;
}
//Writing to file
fwrite(buffer, numbytes, 1, fp);
//printf("\n\nCount: %d Filesize: %d",count,filesize);
//Sending ACK's
typedef unsigned int guint32;
guint32 pos = htonl (count & 0xffffffff);
send(sockfd,(char*) &pos,4,0);
}
}while(count < filesize);
if (count = filesize)
{
printf("\n:>Receiving File Completed\n\n",file);
shutdown(sockfd,2);
closesocket(sockfd);
fclose(fp);
}
else
{
printf("\n:>Receiving File Failed\n\n");
}
Much thanks to anyone who can help me, this is the last thing that needs to work then it's 100% finished!