void *reader_thread(void *arg) { int pos, rh_size, d_size; int status, sock, nbytes_sent, nbytes_recv, backlog; char *str = (char *) arg; char *remote_host, *dir, *port = "80"; char request[255]; struct addrinfo hints, *result, *rp; pos = delimpos(str, '/'); if (pos != -1) { rh_size = pos + 2; d_size = strlen(str) - pos + 2; } else { rh_size = strlen(str) + 1; d_size = 2; } remote_host = (char *) malloc(rh_size * sizeof(char)); dir = (char *) malloc(d_size * sizeof(char)); if (pos != -1) { remote_host = strncpy(remote_host, str, pos); remote_host[strlen(remote_host)] = '\0'; dir = strcpy(dir, str + pos); } else { remote_host = strcpy(remote_host, str); dir = strcpy(dir, "/"); } makerequest(request, dir); memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = 0; hints.ai_protocol = IPPROTO_TCP; if ((status = getaddrinfo(remote_host, port, &hints, &result)) != 0) { printf("getaddrinfo: %s\n", gai_strerror(status)); exit(1); } if ((sock = socket(result->ai_family, result->ai_socktype, result->ai_protocol)) == -1) { perror("socket"); exit(1); } if (connect(sock, result->ai_addr, result->ai_addrlen) == -1) { perror("connect"); exit(1); } if ((nbytes_sent = write(sock, request, strlen(request))) == -1) { perror("send"); exit(1); } while (!eof) { int ret; if (nread >= nwrote) { sem_wait(&sem2); ret = read(sock, buf+nread, sizeof(buf)-nread); sem_post(&sem2); if (ret == 0) { eof = 1; } else { nread += ret; if (nread == sizeof(buf)) nread = 0; if (nread == nwrote) full = 1; empty = 0; } } else { sem_wait(&sem2); ret = read(sock, buf+nread, nwrote-nread); sem_post(&sem2); if (ret == 0) { eof = 1; } else { nread += ret; if (nread == nwrote) full = 1; empty = 0; } } sem_post(&sem1); if (eof) break; //sem_post(&sem1); } free(remote_host); free(dir); freeaddrinfo(result); close(sock); }
/* * Receive a file. */ int tftp_recvfile(int f, union sock_addr *peeraddr, int fd, const char *name, const char *mode) { struct tftphdr *ap; struct tftphdr *dp; int n; volatile u_short block; volatile int size, firsttrip; volatile unsigned long amount; union sock_addr from; socklen_t fromlen; FILE *file; volatile int convert; /* true if converting crlf -> lf */ u_short dp_opcode, dp_block; startclock(); dp = w_init(); ap = (struct tftphdr *)ackbuf; convert = !strcmp(mode, "netascii"); file = fdopen(fd, convert ? "wt" : "wb"); block = 1; firsttrip = 1; amount = 0; bsd_signal(SIGALRM, timer); do { if (firsttrip) { size = makerequest(RRQ, name, ap, mode); firsttrip = 0; } else { ap->th_opcode = htons((u_short) ACK); ap->th_block = htons((u_short) block); size = 4; block++; } timeout = 0; (void)sigsetjmp(timeoutbuf, 1); send_ack: if (trace) tpacket("sent", ap, size); if (sendto(f, ackbuf, size, 0, &(peeraddr->sa), SOCKLEN(peeraddr)) != size) { alarm(0); perror("tftp: sendto"); goto abort; } write_behind(file, convert); for (;;) { alarm(rexmtval); do { fromlen = sizeof(from); n = recvfrom(f, dp, PKTSIZE, 0, &from.sa, &fromlen); } while (n <= 0); alarm(0); if (n < 0) { perror("tftp: recvfrom"); goto abort; } sa_set_port(peeraddr, SOCKPORT(&from)); /* added */ if (trace) tpacket("received", dp, n); /* should verify client address */ dp_opcode = ntohs((u_short) dp->th_opcode); dp_block = ntohs((u_short) dp->th_block); if (dp_opcode == ERROR) { printf("Error code %d: %s\n", dp_block, dp->th_msg); goto abort; } if (dp_opcode == DATA) { int j; if (dp_block == block) { break; /* have next packet */ } /* On an error, try to synchronize * both sides. */ j = synchnet(f); if (j && trace) { printf("discarded %d packets\n", j); } if (dp_block == (block - 1)) { goto send_ack; /* resend ack */ } } } /* size = write(fd, dp->th_data, n - 4); */ size = writeit(file, &dp, n - 4, convert); if (size < 0) { nak(f, peeraddr, errno + 100, NULL); break; } amount += size; } while (size == SEGSIZE); abort: /* ok to ack, since user */ ap->th_opcode = htons((u_short) ACK); /* has seen err msg */ ap->th_block = htons((u_short) block); (void)sendto(f, ackbuf, 4, 0, (struct sockaddr *)peeraddr, SOCKLEN(peeraddr)); write_behind(file, convert); /* flush last buffer */ fclose(file); stopclock(); //if (amount > 0) // printstats("Received", amount); return amount; }
/* * Send the requested file. */ int tftp_sendfile(int f, union sock_addr *peeraddr, int fd, const char *name, const char *mode) { struct tftphdr *ap; /* data and ack packets */ struct tftphdr *dp; int n; volatile int is_request; volatile u_short block; volatile int size, convert; volatile off_t amount; union sock_addr from; socklen_t fromlen; FILE *file; u_short ap_opcode, ap_block; startclock(); /* start stat's clock */ dp = r_init(); /* reset fillbuf/read-ahead code */ ap = (struct tftphdr *)ackbuf; convert = !strcmp(mode, "netascii"); file = fdopen(fd, convert ? "rt" : "rb"); block = 0; is_request = 1; /* First packet is the actual WRQ */ amount = 0; bsd_signal(SIGALRM, timer); do { if (is_request) { size = makerequest(WRQ, name, dp, mode) - 4; } else { /* size = read(fd, dp->th_data, SEGSIZE); */ size = readit(file, &dp, convert); if (size < 0) { nak(f, peeraddr, errno + 100, NULL); break; } dp->th_opcode = htons((u_short) DATA); dp->th_block = htons((u_short) block); } timeout = 0; (void)sigsetjmp(timeoutbuf, 1); if (trace) tpacket("sent", dp, size + 4); n = sendto(f, dp, size + 4, 0, &(peeraddr->sa), SOCKLEN(peeraddr)); if (n != size + 4) { perror("tftp: sendto"); goto abort; } read_ahead(file, convert); for (;;) { alarm(rexmtval); do { fromlen = sizeof(from); n = recvfrom(f, ackbuf, sizeof(ackbuf), 0, &from.sa, &fromlen); } while (n <= 0); alarm(0); if (n < 0) { perror("tftp: recvfrom"); goto abort; } sa_set_port(peeraddr, SOCKPORT(&from)); /* added */ if (trace) tpacket("received", ap, n); /* should verify packet came from server */ ap_opcode = ntohs((u_short) ap->th_opcode); ap_block = ntohs((u_short) ap->th_block); if (ap_opcode == ERROR) { printf("Error code %d: %s\n", ap_block, ap->th_msg); goto abort; } if (ap_opcode == ACK) { int j; if (ap_block == block) { break; } /* On an error, try to synchronize * both sides. */ j = synchnet(f); if (j && trace) { printf("discarded %d packets\n", j); } /* * RFC1129/RFC1350: We MUST NOT re-send the DATA * packet in response to an invalid ACK. Doing so * would cause the Sorcerer's Apprentice bug. */ } } if (!is_request) amount += size; is_request = 0; block++; } while (size == SEGSIZE || block == 1); abort: fclose(file); stopclock(); //if (amount > 0) // printstats("Sent", amount); return amount; }
/* * Send the requested file. */ void sendfile(int fd, char *name, char *mode) { register struct tftphdr *ap; /* data and ack packets */ struct tftphdr *dp; volatile int block = 0, size = 0; int n; volatile unsigned long amount = 0; struct sockaddr_in from; socklen_t fromlen; volatile int convert; /* true if doing nl->crlf conversion */ FILE *file; startclock(); /* start stat's clock */ dp = r_init(); /* reset fillbuf/read-ahead code */ ap = (struct tftphdr *)ackbuf; file = fdopen(fd, "r"); convert = !strcmp(mode, "netascii"); signal(SIGALRM, timer); do { if (block == 0) size = makerequest(WRQ, name, dp, mode) - 4; else { /* size = read(fd, dp->th_data, SEGSIZE); */ size = readit(file, &dp, convert); if (size < 0) { nak(errno + 100); break; } dp->th_opcode = htons((u_short)DATA); dp->th_block = htons((u_short)block); } timeout = 0; (void) sigsetjmp(timeoutbuf, 1); send_data: if (trace) tpacket("sent", dp, size + 4); n = sendto(f, dp, size + 4, 0, (struct sockaddr *)&s_inn, sizeof(s_inn)); if (n != size + 4) { perror("tftp: sendto"); goto abort; } read_ahead(file, convert); for ( ; ; ) { alarm(rexmtval); do { fromlen = sizeof (from); n = recvfrom(f, ackbuf, sizeof (ackbuf), 0, (struct sockaddr *)&from, &fromlen); } while (n <= 0); alarm(0); if (n < 0) { perror("tftp: recvfrom"); goto abort; } s_inn.sin_port = from.sin_port; /* added */ if (trace) tpacket("received", ap, n); /* should verify packet came from server */ ap->th_opcode = ntohs(ap->th_opcode); ap->th_block = ntohs(ap->th_block); if (ap->th_opcode == ERROR) { printf("Error code %d: %s\n", ap->th_code, ap->th_msg); goto abort; } if (ap->th_opcode == ACK) { volatile int j = 0; if (ap->th_block == block) { break; } /* On an error, try to synchronize * both sides. */ j = synchnet(f); if (j && trace) { printf("discarded %d packets\n", j); } if (ap->th_block == (block-1)) { goto send_data; } } } if (block > 0) amount += size; block++; } while (size == SEGSIZE || block == 1); abort: fclose(file); stopclock(); if (amount > 0) printstats("Sent", amount); }