Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <netdb.h>
- #define RSP 0x00 // Response
- #define RQS 0x01 // Request
- #define C_EOF 0x02 // End of file (response)
- #define FILE_N_FND 0x04 // File not Found (response)
- #define MAX_MESSAGE 1400
- /// STRUCT ====================================================================
- /* Protocol for UPACK
- Flags (bit 0 is LSB)
- bit 0 : 1 = request, 0 = response
- bit 1 : 1 = eof encountered (response)
- bit 2 : 1 = file not found (response)
- bit 3 : 1 = invalid request (response)
- bits 4..7 : not used, should be 0
- Length: 16-bit unsigned integer length of requested file block (request), length of data field returned (response).
- Offset: 32-bit unsigned integer offset within a requested file to start supplying data (request and response).
- Filename: 32 byte ASCII character array with requested filename. Filename will be left-justified, and null-terminated.
- Data: not included in request, contains requested file data in response.
- */
- typedef struct UPACK {
- uint8_t flags;
- uint16_t length;
- uint32_t offset;
- unsigned char* filename[MAX_MESSAGE];
- unsigned char data[MAX_MESSAGE];
- } UPACK;
- /// STRUCT ====================================================================
- /**
- Crash handler
- */
- void crash(char *s) {
- perror(s);
- exit(1);
- }
- /**
- Minor Crash handler
- */
- int mcrash(char *s) {
- perror(s);
- return -1;
- }
- // create socket
- // IP protocol family (PF_INET)
- // UDP (SOCK_DGRAM)
- int create_socket() {
- int sock = 0;
- if ((sock = socket(PF_INET, SOCK_DGRAM, 0 )) < 0) crash("Alert Comrade: Socket not created");
- else
- return sock;
- }
- // UDP Using UDP we don't need to call bind unless we
- // want to specify a "source" port number. We really
- // do not care - server will reply to whatever port we
- // are given
- // Make a sockaddr of the server
- // address family is IP (AF_INET)
- // server IP address is found by calling gethostbyname with the
- // name of the server (entered on the command line)
- // note, if an IP address is provided, that is OK too
- //load data into the socket address struct
- void load_socket_address(sockaddr_in * SVR, char* IP, char* PORT) {
- SVR -> sin_family = AF_INET;
- unsigned short tport = 0;
- if(sscanf(PORT, "%hu", &tport) != 1) crash("Alert Comrade: Invalid Port");
- SVR -> sin_port = htons(tport);
- int check = 0;
- check = inet_pton(AF_INET, IP, &SVR -> sin_addr);
- if(check == 1)
- printf("great success\n");
- else if(check == 0)
- printf("no string here\n");
- else if(check == -1)
- printf("bug\n");
- //netdb.h
- //hostent *host;
- //if((host = gethostbyname(PORT)) == 0) crash("Alert Comrade: Invalid/Unknown Host");
- //memcpy(&SVR -> sin_addr.s_addr, host->h_addr, host->h_length);
- SVR -> sin_addr.s_addr = inet_addr(IP);
- printf("Imperial Soviet Comrade: SVN -> sin_family: %d\n", SVR -> sin_family);
- printf("Imperial Soviet Comrade: SVN -> sin_port: %d\n", SVR -> sin_port);
- printf("Imperial Soviet Comrade: SVN -> sin_addr: %d\n", SVR -> sin_addr);
- //printf("Imperial Soviet Comrade: host -> h_addr: %d\n", host->h_addr);
- //printf("Imperial Soviet Comrade: host -> h_length: %d\n", host->h_length);
- }
- //Load the data into the UDP Packet
- void load_UDP_packet(UPACK* UPC, uint8_t FLG, uint16_t LEN, uint32_t OFF) {
- UPC -> flags = FLG;
- UPC -> length = LEN;
- UPC -> offset = OFF;
- //alert the user to the need for data
- printf("Attention Comrade: Enter Message: ");
- char buffer[MAX_MESSAGE];
- //get the next string entered into the command prompt
- fgets(buffer, MAX_MESSAGE, stdin);
- //copy the data from the command prompt into the packet
- memcpy(UPC -> filename, buffer, strlen(buffer));
- }
- //send the packet out
- void send_packet (int SOCKET, UPACK* UPC, sockaddr_in* TARGET) {
- unsigned char* PACKET_DATA = (unsigned char *) UPC;
- printf("\n\nImperial Soviet Comrade: Data in packet dump ::::::::::::::::::::::::::::::::::::::::: start\n");
- printf("Imperial Soviet Comrade: the size of the UPC is %lu\n", (sizeof(*UPC)/8));
- printf("Imperial Soviet Comrade: Socket: %d\n", SOCKET);
- printf("Imperial Soviet Comrade: UPC -> flags: %d\n", UPC -> flags);
- printf("Imperial Soviet Comrade: UPC -> offset: %d\n", UPC -> offset);
- printf("Imperial Soviet Comrade: UPC -> length: %d\n", UPC -> length);
- printf("Imperial Soviet Comrade: UPC -> filename: %s", UPC -> filename);
- printf("Imperial Soviet Comrade: UPC -> data: ");
- for(int i = 0; i < sizeof(UPC -> data); i++) {
- if (((i%80) == 0) && (i != 0)) printf("\nImperial Soviet Comrade: UPC -> data: ");
- printf("%d", ((UPACK *) UPC) -> data[i]);
- }
- printf("\n");
- printf("Imperial Soviet Comrade: sizeof(UPC): %d\n", sizeof(UPC));
- printf("Imperial Soviet Comrade: sockaddr.sin_family: %d\n", TARGET -> sin_family);
- printf("Imperial Soviet Comrade: sockaddr.sin_port: %d\n", TARGET -> sin_port);
- printf("Imperial Soviet Comrade: sockaddr.sin_addr.s_addr: %d\n", TARGET -> sin_addr.s_addr);
- printf("Imperial Soviet Comrade: sizeof(sockaddr): %d\n", sizeof(TARGET));
- printf("Imperial Soviet Comrade: Data in packet dump ::::::::::::::::::::::::::::::::::::::::::: end\n\n\n");
- int size_sent = sendto(SOCKET, UPC, sizeof(UPC)+2*MAX_MESSAGE, 0, (struct sockaddr*) &TARGET, sizeof(TARGET)+2*MAX_MESSAGE);
- printf("Imperial Soviet Comrade: size_sent: %d\n", size_sent);
- if(size_sent < 0) crash("Alert Comrade: Data not sent");
- }
- // Handle returning packets
- int process_incoming(int SOCKET, UPACK* UPC, FILE* TARGET_FILE) {
- // Create a Buffer
- char buffer[MAX_MESSAGE];
- // clear the space
- memset(buffer, 0, MAX_MESSAGE);
- // setup the timeout - 5 seconds
- struct timeval time_out = {5,0};
- // create a file descriptor set
- fd_set incoming_message_socket;
- // zero out the dataset at incoming_message_socket
- FD_ZERO(&incoming_message_socket);
- // Sets the SOCKET as the listened to incoming data
- FD_SET(SOCKET, &incoming_message_socket);
- //originally sock+1
- if (select(SOCKET, &incoming_message_socket, 0, 0, &time_out) < 0)
- return mcrash("Alert Comrade: Error on select\n");
- // something was returned!
- if (FD_ISSET(SOCKET, &incoming_message_socket))
- {
- // Get data back from parts unknown - hopefully the targetted server
- int ECHO = recvfrom(SOCKET, buffer, MAX_MESSAGE, 0, NULL, NULL);
- // something went wrong with receiving
- if (ECHO < 0) crash("Alert Comrade: Error receiving\n");
- // file not found
- else if(UPC -> flags == C_EOF)
- return mcrash("Alert Comrade: File Not Found\n");
- // Something went right! About damn time... It's time to grab this data and toss it into a file!
- else {
- //filename is as what was requested, pointer for writing appends to the end of the file
- for(int i = 0; i < MAX_MESSAGE; i++)
- TARGET_FILE = fopen((const char*) UPC -> filename, (const char*) 'a');
- //print data to file
- fprintf(TARGET_FILE, (const char *) UPC -> data);
- //close the output to the file
- fclose(TARGET_FILE);
- //if the end of file was found
- if(UPC -> flags == C_EOF) return C_EOF;
- //if there is more data to be sent over
- else if(UPC -> flags == RSP) return RSP;
- }
- }
- else return mcrash("Alert Comrade: Timeout - Server is not listening, or packet was dropped.\n");
- return 3;
- }
- int main(int argc, char **argv) {
- using namespace std;
- struct sockaddr_in target;
- //ensure a correct number of arguments
- if(argc != 3) {
- printf("Alert Comrade: invalid number of arguments.\n");
- printf("Command Required: sudo ./a.out 'IP Address' 'Port Number'\n");
- exit(0);
- }
- //create the socket
- int socket = create_socket();
- //load the socket address into target
- load_socket_address(&target, argv[1], argv[2]);
- //create space for the packet
- UPACK *UPACKET = (UPACK *) malloc(sizeof(UPACK));
- //response
- int response_from_server = 0;
- //File to use in order to process requests
- FILE* data_dump;
- //offset counter
- int offset = 0;
- //retry counter
- int retry = 0;
- //Allow the user to send and recieve data
- while(1) {
- //reset offset
- offset = 0;
- // if this is not a resend
- if(response_from_server != 3)
- //fill the packet with data
- load_UDP_packet(UPACKET, RQS, sizeof(UPACKET), offset);
- // if this is trying to resend
- else {
- //add a count to retry
- retry++;
- printf("Imperial Soviet Comrade: Resend Attempt %d\n", retry);
- }
- //shoot that packet down the wire
- send_packet(socket, UPACKET, &target);
- //recieve the packet
- response_from_server = process_incoming(socket, UPACKET, data_dump);
- //There's more data to be sent
- if(response_from_server == RSP) {
- retry = 0;
- while(response_from_server == RSP) {
- //fill the packet with data, increment the offset
- load_UDP_packet(UPACKET, RQS, sizeof(UPACKET), offset++);
- //shoot that packet down the wire
- send_packet(socket, UPACKET, &target);
- //recieve the packet
- response_from_server = process_incoming(socket, UPACKET, data_dump);
- }
- }
- else if (response_from_server == C_EOF) {
- printf("Imperial Soviet Comrade: File Fully Recieved\n");
- }
- else if (retry >= 3) {
- printf("Imperial Soviet Comrade: Transmission Failed 3 Times. Closing Connection to Server.\n");
- retry = 0;
- }
- // do nothing - EOF lets you know by coming back aroumd
- }
- return(0);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement