# HG changeset patch # User Eric Warmenhoven # Date 957664206 0 # Node ID b2f9f629525ea04d7f6792fd1ecaa2d4dc696346 # Parent d25b1484011be0a74a8e77ff404da4d14125dec9 [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 diff -r d25b1484011b -r b2f9f629525e src/rvous.c --- 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)