changeset 221:b2f9f629525e

[gaim-migrate @ 231] Added on the beginnings of file sending. Win clients can now figure out which file you're *trying* to send them, but can't get it. The AIM method of Get File is really fscked up, IMHO. I don't know if any of you are familiar with it, but I'll describe it. Some user decides they want to download a file from another user, so they choose Get File. It then returns a list of files available from that person, and they can choose which ones they want to download. The other person can't decide on a user-by-user basis which files are listed, only if any files are listed at all (not allowing people to download them). The way I'm going to implement it is when someone gets a message that another person is trying to download a file from them, it asks them which file they want to make available. You can only do one file at a time this way, but that's tough if you want to be downloading more than one file. Use gnutella or FTP or something that's better designed for it than AIM. But the way the win AIM clients are now, it acts as a public ftp server, and I think it shouldn't. committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Sun, 07 May 2000 01:50:06 +0000
parents d25b1484011b
children 12a39dcb681c
files src/rvous.c
diffstat 1 files changed, 160 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/src/rvous.c	Sun May 07 01:04:28 2000 +0000
+++ b/src/rvous.c	Sun May 07 01:50:06 2000 +0000
@@ -136,6 +136,41 @@
 	g_free(fname);
 }
 
+static int read_file_header(int fd, struct file_header *header) {
+	char buf[257];
+	int read_rv = read(fd, buf, 256);
+	memcpy(&header->magic,		buf +   0,  4);
+	memcpy(&header->hdrlen,		buf +   4,  2);
+	memcpy(&header->hdrtype,	buf +   6,  2);
+	memcpy(&header->bcookie,	buf +   8,  8);
+	memcpy(&header->encrypt,	buf +  16,  2);
+	memcpy(&header->compress,	buf +  18,  2);
+	memcpy(&header->totfiles,	buf +  20,  2);
+	memcpy(&header->filesleft,	buf +  22,  2);
+	memcpy(&header->totparts,	buf +  24,  2);
+	memcpy(&header->partsleft,	buf +  26,  2);
+	memcpy(&header->totsize,	buf +  28,  4);
+	memcpy(&header->size,		buf +  32,  4);
+	memcpy(&header->modtime,	buf +  36,  4);
+	memcpy(&header->checksum,	buf +  40,  4);
+	memcpy(&header->rfrcsum,	buf +  44,  4);
+	memcpy(&header->rfsize,		buf +  48,  4);
+	memcpy(&header->cretime,	buf +  52,  4);
+	memcpy(&header->rfcsum,		buf +  56,  4);
+	memcpy(&header->nrecvd,		buf +  60,  4);
+	memcpy(&header->recvcsum,	buf +  64,  4);
+	memcpy(&header->idstring,	buf +  68, 32);
+	memcpy(&header->flags,		buf + 100,  1);
+	memcpy(&header->lnameoffset,	buf + 101,  1);
+	memcpy(&header->lsizeoffset,	buf + 102,  1);
+	memcpy(&header->dummy,		buf + 103, 69);
+	memcpy(&header->macfileinfo,	buf + 172, 16);
+	memcpy(&header->nencode,	buf + 188,  2);
+	memcpy(&header->nlanguage,	buf + 190,  2);
+	memcpy(&header->name,		buf + 192, 64);
+	return read_rv;
+}
+
 static int write_file_header(int fd, struct file_header *header) {
 	char buf[257];
 	memcpy(buf +   0, &header->magic,	 4);
@@ -213,7 +248,7 @@
 		return;
 	}
 
-	read_rv = read(ft->fd, header, 256);
+	read_rv = read_file_header(ft->fd, header);
 	if(read_rv < 0) {
 		close(ft->fd);
 		fclose(ft->f);
@@ -279,6 +314,8 @@
 					gtk_main_iteration();
 				continue;
 			}
+			gtk_widget_destroy(fw);
+			fw = NULL;
 			fclose(ft->f);
 			close(ft->fd);
 			g_free(buf);
@@ -333,9 +370,12 @@
 	struct file_header *fhdr = g_new0(struct file_header, 1);
 	struct sockaddr_in sin;
 	guint32 rcv;
+	int cont;
 	char *c;
 	struct stat st;
 	struct tm *fortime;
+	GtkWidget *fw = NULL, *fbar = NULL, *label = NULL;
+	GtkWidget *button = NULL, *pct = NULL;
 
 	stat(file, &st);
 	if (!(ft->f = fopen(file, "r"))) {
@@ -345,6 +385,7 @@
 		g_free(buf);
 		ft->accepted = 0;
 		accept_callback(NULL, ft);
+		free_ft(ft);
 		return;
 	}
 
@@ -359,13 +400,11 @@
 
 
 
-	sin.sin_addr.s_addr = inet_addr(ft->ip);
-	sin.sin_family = AF_INET;
-	sin.sin_port = htons(ft->port);
+	ft->fd = connect_address(inet_addr(ft->ip), ft->port);
 
-	ft->fd = socket(AF_INET, SOCK_STREAM, 0);
-
-	if (ft->fd <= -1 || connect(ft->fd, (struct sockaddr *)&sin, sizeof(sin))) {
+	if (ft->fd <= -1) {
+		g_free(fhdr);
+		free_ft(ft);
 		return;
 	}
 
@@ -376,6 +415,10 @@
 	 * 4. receive header
 	 *
 	 * then we need to wait to actually send the file.
+	 *
+	 * 5. either (receive header) or (remote host cancels)
+	 * 6. if received header, send file
+	 * 7. ? haven't gotten this far yet
 	 */
 
 	/* 1. build/send header */
@@ -398,9 +441,9 @@
 	fhdr->partsleft = htons(1);
 	fhdr->totsize = htonl((long)st.st_size); /* combined size of all files */
 	/* size = strlen("mm/dd/yyyy hh:mm sizesize 'name'\r\n") */
-	fhdr->size = htonl(30 + strlen(c)); /* size of listing.txt */
+	fhdr->size = htonl(28 + strlen(c)); /* size of listing.txt */
 	fhdr->modtime = htonl(time(NULL)); /* time since UNIX epoch */
-	fhdr->checksum = htonl(0x89f70000); /* ? */
+	fhdr->checksum = htonl(0x89f70000); /* ? i don't think this matters */
 	fhdr->rfrcsum = 0;
 	fhdr->rfsize = 0;
 	fhdr->cretime = 0;
@@ -420,18 +463,22 @@
 	if (read_rv <= -1) {
 		sprintf(debug_buff, "Couldn't write opening header\n");
 		debug_print(debug_buff);
+		g_free(fhdr);
 		close(ft->fd);
+		free_ft(ft);
 		return;
 	}
 
 	/* 2. receive header */
 	sprintf(debug_buff, "Receiving header\n");
 	debug_print(debug_buff);
-	read_rv = read(ft->fd, fhdr, 256);
+	read_rv = read_file_header(ft->fd, fhdr);
 	if (read_rv <= -1) {
 		sprintf(debug_buff, "Couldn't read header\n");
 		debug_print(debug_buff);
+		g_free(fhdr);
 		close(ft->fd);
+		free_ft(ft);
 		return;
 	}
 
@@ -454,34 +501,130 @@
 	if (read_rv <= -1) {
 		sprintf(debug_buff, "Could not send file, wrote %d\n", rcv);
 		debug_print(debug_buff);
+		g_free(buf);
+		g_free(fhdr);
 		close(ft->fd);
+		free_ft(ft);
 		return;
 	}
+	g_free(buf);
 
 	/* 4. receive header */
 	sprintf(debug_buff, "Receiving closing header\n");
 	debug_print(debug_buff);
-	read_rv = read(ft->fd, fhdr, 256);
+	read_rv = read_file_header(ft->fd, fhdr);
 	if (read_rv <= -1) {
 		sprintf(debug_buff, "Couldn't read closing header\n");
 		debug_print(debug_buff);
+		g_free(fhdr);
 		close(ft->fd);
+		free_ft(ft);
 		return;
 	}
 
 	/* 5. wait to see if we're sending it */
-	/* read_rv = read(ft->fd, fhdr, 256);
-	 * if (read_rv <= -1 !! connection_is_closed()) { // uh huh
-	 * 	clean_up();
-	 * 	return();
-	 * }
-	 */
+	fcntl(ft->fd, F_SETFL, O_NONBLOCK);
+	rcv = 0;
+	while (rcv != 256) {
+		int i;
+		read_rv = read_file_header(ft->fd, fhdr);
+		if(read_rv < 0) {
+			if (errno == EWOULDBLOCK) {
+				while(gtk_events_pending())
+					gtk_main_iteration();
+				continue;
+			}
+			fclose(ft->f);
+			close(ft->fd);
+			g_free(fhdr);
+			free_ft(ft);
+			return;
+		}
+		rcv += read_rv;
+	}
 
 	/* 6. send the file */
+	fw = gtk_dialog_new();
+	buf = g_malloc(2048);
+	snprintf(buf, 2048, "Sending %s to %s", fhdr->name, ft->user);
+	label = gtk_label_new(buf);
+	gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fw)->vbox), label, 0, 0, 5);
+	gtk_widget_show(label);
+	fbar = gtk_progress_bar_new();
+	gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fw)->action_area), fbar, 0, 0, 5);
+	gtk_widget_show(fbar);
+	pct = gtk_label_new("0 %");
+	gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fw)->action_area), pct, 0, 0, 5);
+	gtk_widget_show(pct);
+	button = gtk_button_new_with_label("Cancel");
+	gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fw)->action_area), button, 0, 0, 5);
+	gtk_widget_show(button);
+	gtk_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc)toggle, &cont);
+	gtk_window_set_title(GTK_WINDOW(fw), "Gaim - File Transfer");
+	gtk_widget_realize(fw);
+	aol_icon(fw->window);
+	gtk_widget_show(fw);
+
+	sprintf(debug_buff, "Sending %s to %s (%d bytes)\n", fhdr->name,
+			ft->user, fhdr->totsize);
+	debug_print(debug_buff);
+
+	rcv = 0; cont = 1;
+	while (rcv != fhdr->totsize && cont) {
+		int i;
+		float pcnt = ((float)rcv)/((float)fhdr->totsize);
+		int remain = fhdr->totsize - rcv > 1024 ? 1024 : fhdr->totsize - rcv;
+		for (i = 0; i < 1024; i++)
+			fscanf(ft->f, "%c", &buf[i]);
+		read_rv = write(ft->fd, buf, remain);
+		if (read_rv < 0) {
+			if (errno == EWOULDBLOCK) {
+				while (gtk_events_pending())
+					gtk_main_iteration();
+				continue;
+			}
+			fclose(ft->f);
+			gtk_widget_destroy(fw);
+			fw = NULL;
+			fclose(ft->f);
+			close(ft->fd);
+			g_free(buf);
+			g_free(fhdr);
+			free_ft(ft);
+			return;
+		}
+		rcv += read_rv;
+		gtk_progress_bar_update(GTK_PROGRESS_BAR(fbar), pcnt);
+		sprintf(buf, "%d / %d K (%2.0f %%)", rcv/1024, ft->size/1024, 100*pcnt);
+		gtk_label_set_text(GTK_LABEL(pct), buf);
+		while(gtk_events_pending())
+			gtk_main_iteration();
+	}
+	fclose(ft->f);
+	gtk_widget_destroy(fw);
+	fw = NULL;
+
+	if (!cont) {
+		char *tmp = frombase64(ft->cookie);
+		sprintf(buf, "toc_rvous_cancel %s %s %s", ft->user, tmp, ft->UID);
+		sflap_send(buf, strlen(buf), TYPE_DATA);
+		g_free(buf);
+		close(ft->fd);
+		free_ft(ft);
+		g_free(fhdr);
+		return;
+	}
+
+	sprintf(debug_buff, "Upload complete.\n");
+	debug_print(debug_buff);
 
 	/* 7. receive closing header */
 
 	/* done */
+	close(ft->fd);
+	g_free(buf);
+	g_free(fhdr);
+	free_ft(ft);
 }
 
 void accept_file_dialog(struct file_transfer *ft)