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!

When your server starts sending a large file (line 195) it stops paying attention to incoming data, until the file is completely transmitted. Its incoming buffer fills up. After that, the client can't send anything and gets stuck at line 90. The server keeps sending. Client's buffer fills up. Now both are stuck.

You need to seriously rethink the server design.

PS: I am not familiar with DDC spec, but TCP and packets do not go together. Seems like you are missing something.

PPS:

}while(count < filesize);

How does filesize gets initialized?

Edited 5 Years Ago by nezachem: n/a

Of course it is declared. How it is initialized mean how does it receive its initial value. So, where in your code filesize gets initialized?

atoi(output[8])

It's a variable with the length of the file I receive via socket

This article has been dead for over six months. Start a new discussion instead.