int main(int argc, char **argv) { /* local client data */ int sockfd; /* file descriptor for endpoint */ struct sockaddr_in client_sockaddr; /* address/port pair */ struct in_addr client_addr; /* network-format address */ char client_dotted[INET_ADDRSTRLEN];/* human-readable address */ int client_port; /* local port */ /* remote server data */ char *server_dotted; /* human-readable address */ int server_port; /* remote port */ /* the request */ char *filename; /* filename to request */ /* read arguments */ if (argc != 5) { fprintf(stderr, "client: wrong number of arguments\n"); client_usage(); exit(1); } server_dotted = argv[1]; server_port = atoi(argv[2]); client_port = atoi(argv[3]); filename = argv[4]; if (!client_arguments_valid( server_dotted, server_port, client_port, filename)) { client_usage(); exit(1); } /* get the primary IP address of this host */ get_primary_addr(&client_addr); inet_ntop(AF_INET, &client_addr, client_dotted, INET_ADDRSTRLEN); /* construct an endpoint address with primary address and desired port */ memset(&client_sockaddr, 0, sizeof(client_sockaddr)); client_sockaddr.sin_family = PF_INET; memcpy(&client_sockaddr.sin_addr,&client_addr,sizeof(struct in_addr)); client_sockaddr.sin_port = htons(client_port); /* make a socket*/ sockfd = socket(PF_INET, SOCK_DGRAM, 0); if (sockfd<0) { perror("can't open socket"); exit(1); } /* bind it to an appropriate local address and port */ if (bind(sockfd, (struct sockaddr *) &client_sockaddr, sizeof(client_sockaddr))<0) { perror("can't bind local address"); exit(1); } fprintf(stderr, "client: Receiving on %s, port %d\n", client_dotted, client_port); /* send a command */ send_command(sockfd, server_dotted, server_port, filename, 0, MAXINT); fprintf(stderr, "client: requesting %s blocks %d-%d\n", filename, 0, MAXINT); /* receive the whole document and make naive assumptions */ int done = FALSE; // set to TRUE when you think you're done int init = TRUE; /* create a bit array to test which blocks have been received */ struct bits blocksRecv; /* open a file to write to in the current directory */ FILE *download = fopen(filename, "w"); fclose(download); int outfd = open(filename, O_RDWR); while (!done) { int retval; again: if ((retval = select_block(sockfd, 0, 20000))==0) { /* timeout */ struct range nBlocks[12]; int currentRange = 0; int i; int check = 0; int numBlocks = blocksRecv.nbits; for(i = 0; i < numBlocks; i++){ /* look for the start of a missed block */ if(check == 0 && bits_testbit(&blocksRecv, i)){ nBlocks[currentRange].first_block = i; nBlocks[currentRange].last_block = numBlocks-1; check++; } /* look for the end of a missed block */ else if(check == 1 && !(bits_testbit(&blocksRecv, i))){ nBlocks[currentRange].last_block = i-1; currentRange ++; /* if you have found 12 missed blocks, send_commands */ if(currentRange == 12){ send_commands(sockfd, server_dotted, server_port, filename, nBlocks, currentRange); currentRange = 0; } check = 0; } } /* send any left over blocks from the loop above */ send_commands(sockfd, server_dotted, server_port, filename, nBlocks, currentRange); if(bits_empty(&blocksRecv)){ done = TRUE; } } else if (retval<0) { /* error */ perror("select"); fprintf(stderr, "client: receive error\n"); } else { /* input is waiting, read it */ struct sockaddr_in resp_sockaddr; /* address/port pair */ int resp_len; /* length used */ char resp_dotted[INET_ADDRSTRLEN]; /* human-readable address */ int resp_port; /* port */ int resp_mesglen; /* length of message */ struct block one_block; /* use helper routine to receive a block */ recv_block(sockfd, &one_block, &resp_sockaddr); /* get human-readable internet address */ inet_ntop(AF_INET, (void *)&(resp_sockaddr.sin_addr.s_addr), resp_dotted, INET_ADDRSTRLEN); resp_port = ntohs(resp_sockaddr.sin_port); fprintf(stderr, "client: %s:%d sent %s block %d (range 0-%d)\n", resp_dotted, resp_port, one_block.filename, one_block.which_block, one_block.total_blocks); /* check block data for errors */ if (strcmp(filename, one_block.filename)!=0) { fprintf(stderr, "client: received block with incorrect filename %s\n", one_block.filename); goto again; } /* init the bit array once you know how many blocks the file contains */ if(init){ //fprintf(stderr, "total blocks: %d\n", one_block.total_blocks); bits_alloc(&blocksRecv, one_block.total_blocks); bits_setrange(&blocksRecv, 0, one_block.total_blocks - 1); init = FALSE; } /* if you have not received the current block, write it and flag it as received */ if(bits_testbit(&blocksRecv, one_block.which_block)){ bits_clearbit(&blocksRecv, one_block.which_block); lseek(outfd, one_block.which_block*PAYLOADSIZE, SEEK_SET); write(outfd, one_block.payload, one_block.paysize); } /* if all blocks have been received, done */ if(bits_empty(&blocksRecv)){ done = TRUE; } } } /* close the file stream */ close(outfd); }
unsigned char * s3_signed_request( unsigned char * resource, unsigned char * server_domain, unsigned char * s3_general_key, unsigned char * timestamp, unsigned char * authorization_token, long int start_byte, long int end_byte){ //Set up the socket to Amazon int s3sockfd, portno, n; struct sockaddr_in serv_addr; struct hostent *server; portno = 80; s3sockfd = socket(AF_INET, SOCK_STREAM, 0); server = gethostbyname(server_domain); if (server == NULL){ printf("trouble connecting"); return NULL; } bzero((char *) &serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length); serv_addr.sin_port = htons(portno); if (connect(s3sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) { printf("ERROR CONNECTING"); return NULL; } /* * If we want the function to create the timestamp. * This is difficult because it must match the * signed token to the second or Amazon will deny it. time_t timer; char time_buffer[55]; struct tm* tm_info; time(&timer); tm_info = localtime(&timer); strftime(time_buffer, 55, "%a, %d %b %Y %OH:%M:%S %Z", tm_info); */ unsigned char * request_string; request_string = malloc(sizeof(unsigned char)*256); //Write the hand crafted string. sprintf(request_string, "GET %s HTTP/1.1\r\nHost: %s\r\n" "Date: %s\r\nRange: bytes=%i-%i\r\n" "Authorization: AWS %s:%s\r\n\r\n", resource, server_domain, timestamp, start_byte, end_byte, s3_general_key, authorization_token); //Send the string and receive the file if (write(s3sockfd,curlbuffer,strlen(request_string)) < 0 ){ printf("error writing to socket\n"); return -1; } int receive_size = (end_byte - start_byte)+1; unsigned char * data_buffer = malloc(sizeof(unsigned char)* receive_size); int bytes_received = recv_block(s3sockfd, data_buffer, receive_size); //CLEANUP free(request_string); close(s3sockfd); return (data_buffer); }