Esempio n. 1
0
int
main (int argc, char *const *argv)
{
  char command;

  /* FIXME: Localisation is meaningless, unless --help and --version are
     locally used.  Localisation would be best accomplished by the calling
     tar, on messages found within error packets.  */

#if DOSWIN
  program_name = get_program_base_name (argv[0]);
#else
  program_name = argv[0];
#endif

  setlocale (LC_ALL, "");
  bindtextdomain (PACKAGE, LOCALEDIR);
  textdomain (PACKAGE);

  /* FIXME: Implement --help and --version as per GNU standards.  */

  argc--, argv++;
  if (argc > 0)
    {
      debug_file = fopen (*argv, "w");
      if (debug_file == 0)
	{
	  return_numbered_error (errno);
	  exit (EXIT_FAILURE);
	}
      setbuf (debug_file, NULL);
    }

  while (full_read (INPUT, &command, 1) == 1)
    {
      errno = 0;		/* FIXME: errno should be read-only */

      switch (command)
	{
	  /* FIXME: Maybe 'H' and 'V' for --help and --version output?  */

	case 'O':
	  {
	    char device_string[STRING_SIZE];
	    char mode_string[STRING_SIZE];

	    get_string (device_string);
	    get_string (mode_string);
	    DEBUG2 ("rmtd: O %s %s\n", device_string, mode_string);

	    if (tape >= 0)
	      close (tape);

#if defined (i386) && defined (AIX)

	    /* This is alleged to fix a byte ordering problem.  I'm quite
	       suspicious if it's right. -- mib.  */

	    {
	      mode_t old_mode = atoi (mode_string);
	      mode_t new_mode = 0;

	      if ((old_mode & 3) == 0)
		new_mode |= O_RDONLY;
	      if (old_mode & 1)
		new_mode |= O_WRONLY;
	      if (old_mode & 2)
		new_mode |= O_RDWR;
	      if (old_mode & 0x0008)
		new_mode |= O_APPEND;
	      if (old_mode & 0x0200)
		new_mode |= O_CREAT;
	      if (old_mode & 0x0400)
		new_mode |= O_TRUNC;
	      if (old_mode & 0x0800)
		new_mode |= O_EXCL;
	      tape = open (device_string, new_mode, 0666);
	    }
#else
	    tape = open (device_string, atoi (mode_string), 0666);
#endif
	    if (tape < 0)
	      return_numbered_error (errno);
	    else
	      return_response (0);
	    break;
	  }

	case 'C':
	  {
	    char device_string[STRING_SIZE];

	    get_string (device_string); /* discard */
	    DEBUG ("rmtd: C\n");

	    if (close (tape) < 0)
	      return_numbered_error (errno);
	    else
	      {
		tape = -1;
		return_response (0);
	      }
	    break;
	  }

	case 'L':
	  {
	    int status = 0;
	    char count_string[STRING_SIZE];
	    char position_string[STRING_SIZE];

	    get_string (count_string);
	    get_string (position_string);
	    DEBUG2 ("rmtd: L %s %s\n", count_string, position_string);

	    status = lseek (tape, (off_t) atol (count_string),
			    atoi (position_string));
	    if (status < 0)
	      return_numbered_error (errno);
	    else
	      return_response (status);
	    break;
	  }

	case 'W':
	  {
	    char count_string[STRING_SIZE];
	    ssize_t size_read = 0;
	    ssize_t size_written;
	    size_t counter;
	    int size;

	    get_string (count_string);
	    size = atoi (count_string);
	    DEBUG1 ("rmtd: W %s\n", count_string);

	    prepare_record_buffer (size);
	    for (counter = 0; counter < size; counter += size_read)
	      {
		size_read
		  = full_read (INPUT, record_buffer + counter, size - counter);
		if (size_read <= 0)
		  {
		    return_error_message (N_("Premature end of file"));
		    /* Exit status used to be 2.  */
		    exit (EXIT_FAILURE);
		  }
	      }
	    size_written = full_write (tape, record_buffer, size);
	    if (size_written < 0)
	      return_numbered_error (errno);
	    else
	      return_response (size_written);
	    break;
	  }

	case 'R':
	  {
	    char count_string[STRING_SIZE];
	    size_t size;
	    ssize_t read_size;

	    get_string (count_string);
	    DEBUG1 ("rmtd: R %s\n", count_string);

	    size = atoi (count_string);
	    prepare_record_buffer (size);
	    read_size = full_read (tape, record_buffer, size);
	    if (read_size < 0)
	      return_numbered_error (errno);
	    else
	      {
		sprintf (reply_buffer, "A%d\n", read_size);
		full_write (OUTPUT, reply_buffer, strlen (reply_buffer));
		full_write (OUTPUT, record_buffer, read_size);
	      }
	    break;
	  }

	case 'I':
	  {
	    int status = 0;
	    char operation_string[STRING_SIZE];
	    char count_string[STRING_SIZE];

	    get_string (operation_string);
	    get_string  (count_string);
	    DEBUG2 ("rmtd: I %s %s\n", operation_string, count_string);

#ifdef MTIOCTOP
	    {
	      struct mtop mtop;

	      mtop.mt_op = atoi (operation_string);
	      mtop.mt_count = atoi (count_string);
	      if (ioctl (tape, MTIOCTOP, (char *) &mtop) < 0)
		{
		  return_numbered_error (errno);
		  break;
		}
	      status = mtop.mt_count;
	    }
#endif
	    return_response (status);
	    break;
	  }

	case 'S':
	  {
	    int status = 0;

	    DEBUG ("rmtd: S\n");

#ifdef MTIOCGET
	    {
	      struct mtget operation;

	      if (ioctl (tape, MTIOCGET, (char *) &operation) < 0)
		{
		  return_numbered_error (errno);
		  break;
		}
	      status = sizeof (operation);
	      sprintf (reply_buffer, "A%d\n", status);
	      full_write (OUTPUT, reply_buffer, strlen (reply_buffer));
	      full_write (OUTPUT, (char *) &operation, sizeof (operation));
	    }
#endif
	    /* FIXME: No reply at all, here?  */
	    break;
	  }

	default:
	  DEBUG1 (_("rmtd: Garbage command %c\n"), command);
	  return_error_message (N_("Garbage command"));
	  /* Exit status used to be 3.  */
	  exit (EXIT_FAILURE);
	}
    }

  exit (EXIT_SUCCESS);
}
Esempio n. 2
0
/**
* handle_client:  Main application layer thread for each client
* @author ndemarinis (Basic implementation)
*/
void *handle_client(void *data){
    struct client_handler_data *clnt = (struct client_handler_data *)data;
    
    int pipes[2]; // Make a pipe to connect to the layer stack
    uint16_t cur_seq_num = 0;
    
    pid_t clnt_pid; // PID we receive from the client before startup
    struct layer_stack *stack; // Work data for layer stack implementation

    // Grab the client's identifier
    if((recv(clnt->sock, &clnt_pid, sizeof(pid_t), 0) != sizeof(pid_t)))
      die_with_error("Error receiving PID from client!");

    stack = create_layer_stack(clnt->sock, clnt_pid, pipes); // Initialize all of our layer threads

    sleep(1); // Wait a second for the thread creation to settle


    int bytes_read;
    struct packet client_p;
    struct packet response_p;
    while(1){
        //Wait for a packet to come in
        bytes_read = read(pipe_read(pipes), &client_p, sizeof(struct packet));

	if(!bytes_read) // If we read nothing, it's time to terminate.  
	  {
	    dprintf(DID_INFO, "APP:  Read 0 bytes from layer stack.  Terminating!\n");
	    break;
	  }

        int opcode = client_p.opcode;
        //login
        if (opcode == __LOGIN_CODE){
            //payload is just the username for this opcode
            if(login(client_p.payload) == 0){
                //response code for SUCCESS
                response_p.opcode = 0x05;
                response_p.seq_num = cur_seq_num;
                cur_seq_num++;
                //no payload basic success response!
                response_p.length = 0;

                send_packet(pipes, response_p);
            } else {
                //basic response packet signaling invailed login
                response_p.opcode = __NOT_AUTHORIZED_CODE;
                response_p.seq_num = cur_seq_num;
                cur_seq_num++;
                response_p.length = 0;

                send_packet(pipes, response_p);
            }
        //create record
        } else if (opcode == __CREATE_CODE){
            //payload syntax "<firstName>,<lastName>,<location>"
            char *firstName = strtok(client_p.payload, ",");
            char *lastName = strtok(NULL, ",");
            char *location = strtok(NULL, "");

            //replace null with proper response once I determine what its for!
            char *response = malloc(10*sizeof(response));
            int resp = createRecord(firstName, lastName, location, response);
            //if a 0 was not returned an error occured
            if (resp) {
                //send an error back!
                return_error(pipes, resp, &cur_seq_num);
            } else {
                //send back the data
                return_response(pipes, response, &cur_seq_num);
            }
        //query record
        } else if (opcode == __QUERY_CODE){
            //payload syntax "NAME:<firstName>,<lastName>"
            //               "LOCATION:<location>"
            char *queryType = strtok(client_p.payload, ":");

            bodyEntry *responses;
            int resp;
            //two types of query name and location
            if (strcmp(queryType, "NAME") == 0){
                //handle queries by name
                char *firstName = strtok(NULL, ",");
                char *lastName = strtok(NULL, "");
                
		int respCount;
                //get the query response from the database
                resp = queryRecordByName(firstName, lastName, &responses, &respCount);

                //if resp is not 0 then an error occured
                if (resp){
                    //send an error back!
                    return_error(pipes, resp, &cur_seq_num);
                } else {
                    //send the information back to the client!
                    char response[respCount*(16+20+36+3)];
		    memset(response,0,sizeof(response));
                    int i, rID;
		    char recordID[10];
                    for (i = 0; i < respCount; i++){
                        rID = responses[i].id;
                        sprintf(recordID, "%09d", rID);
                        strcat(response, recordID);
                        strcat(response, ",");
                        strcat(response, responses[i].location);
                        strcat(response, ",");
                    }
                    return_response(pipes, response, &cur_seq_num);
                }
            } else if (strcmp(queryType, "LOCATION") == 0){
                //handle queries by location
                char *location = strtok(NULL, "");

		int respCount;
                //get the query response from the database
                resp = queryRecordByLocation(location, &responses, &respCount);

                //if resp is not 0 then an error occured
                if (resp){
                    //send an error back!
                    return_error(pipes, resp, &cur_seq_num);
                } else {
                    //send the information back to the client!
                    char response[respCount*(16+20+36+3)];
		    memset(response,0,sizeof(response));
                    int i, rID;
		    char recordID[10];
                    for (i = 0; i < respCount; i++){
                        rID = responses[i].id;
                        sprintf(recordID, "%09d", rID);
                        strcat(response, recordID);
                        strcat(response, ",");
                        strcat(response, responses[i].firstName);
                        strcat(response, ",");
                        strcat(response, responses[i].lastName);
                        strcat(response, ",");
                    }
                    return_response(pipes, response, &cur_seq_num);
                }
            }
        //update record
        } else if (opcode == __UPDATE_CODE){
            //payload syntax "<recordId>,<firstName>,<lastName>"
            char *recordId = strtok(client_p.payload, ",");
            char *firstName = strtok(NULL, ",");
            char *lastName = strtok(NULL, "");

            //convert recordID into an integer
            int rId = atoi(recordId);
            int resp = updateRecordName(rId, firstName, lastName);

            //if resp is not 0 then an error occured
            if (resp){
                //send an error back!
                return_error(pipes, resp, &cur_seq_num);
            } else {
                //send the information back to the client!
                //basic success packet so an empty string is given for the payload
                return_response(pipes, "", &cur_seq_num);
            }
        //add picture
        } else if (opcode == __ADD_PIC_CODE){
            /*payload syntax 1st   packet:   "<firstName>,<lastName>,<imageSize>"
                             2nd+ packets:   "<pictureData>"
                             These picture data packets will continue until the entirety of the picture has been transmitted
                             The file is complete once the server has recieved a packet ending with an EOF character
            */
            //get the name information from the first packet transmitted
            char *firstName = strtok(client_p.payload, ",");
            char *lastName = strtok(NULL, ",");
            char *imageSize = strtok(NULL, "");

            unsigned long size = atol(imageSize);

            //create an array capable of holding the entire image
            char pictureData[size];
            int i = 0;

	    // DEBUG:  Write out the file as we read it
	    FILE *out = fopen("server_output.png", "w+");

            //start recieving the picture data, continue until this entire picture has been recieved
            while(i < size - 1){
                //read in a new packet of data
                bytes_read = read(pipe_read(pipes), &client_p, sizeof(struct packet));
		dprintf(DID_APP_INFO, "APP:  Received packet of %d bytes with payload of %d bytes.\n", 
		       bytes_read, client_p.length);

                //store the picture data into the array
                memcpy(pictureData + i, client_p.payload, client_p.length);

                //increment i by the length of the payload
                i += client_p.length;
            }

	    // DEBUG:  Write out that whole array to the test file
	    printf("Received picture of %d total bytes.\n", i);
	    write(fileno(out), pictureData, i);

	    // DEBUG:  Close that file
	    fflush(out);
	    fclose(out);	    

            char add_response[10];
            int resp = addPicture(firstName, lastName, pictureData, add_response);

            if (resp){
                //send an error back!
                return_error(pipes, resp, &cur_seq_num);
            } else {
                //send the information back to the client!
                return_response(pipes, add_response, &cur_seq_num);
            }

        //connect picture
        } else if (opcode == __CONNECT_PIC_CODE){
            //payload syntax "<pictureID>,<recordID>"
            char *pictureID = strtok(client_p.payload, ",");
            char *recordID = strtok(NULL, "");

            int pID = atoi(pictureID);
            int rID = atoi(recordID);

            int resp = connectPictureToRecord(pID, rID);

            if (resp){
                //send and error back!
                return_error(pipes, resp, &cur_seq_num);
            } else {
                //send the success packet back!
                return_response(pipes, "", &cur_seq_num);
            }
        //logout!
        } else if (opcode == __LOGOUT_CODE){
            //payload syntax NONE
            //break out of the while loop containin this and allow the thread processing this client to exit
	    logout();
            break;
        //download picture
        } else if (opcode == __QUERY_PIC_CODE){
            //payload syntax "<pictureID>"
            char *pictureID = strtok(client_p.payload, "");
            int pID = atoi(pictureID);

            char pictureData[__MAX_IMAGE_SIZE];
            int resp = queryPicture(pID, pictureData);

            if (resp){
                //send an error back!
                return_error(pipes, resp, &cur_seq_num);
            } else {
                //break the image into packets and send it back to the client!
                //write the data into a tempory file handle for simple reading when breaking into packets
                //base the temporary file off of the pid to ensure uniqueness
                char filename[MAX_FILENAME_SIZE];
                int pid = getpid();
                char cpid[10];
                sprintf(cpid, "%d", pid);
                strcpy(filename, "temp_");
                strcat(filename, cpid);
                strcat(filename, ".jpg");
                //open the temp file for writing
                FILE *picture = fopen(filename, "w");
                //write the entire image to the file!
                fwrite(pictureData, 1, sizeof(pictureData), picture);

                //send a simple packet informing the client of the size of the image that it is going to recieve
                response_p.opcode = 5;
                response_p.seq_num = cur_seq_num;
                cur_seq_num++;
                sprintf(response_p.payload, "%lu", sizeof(pictureData));
                response_p.length = strlen(response_p.payload);
                send_packet(pipes, response_p);

                //read into packets and send them until the end of file is reached
                //note this uses the same packet pointer the entire time so the opcode does not need to be set again
                response_p.opcode = 5;
                while(!feof(picture)){
                    //read at most 251 bytes of the picture into the packets payload
                    int readSize = fread(response_p.payload, 1, MAX_PAYLOAD, picture);
                    //if there was no error then add the sequence number and the length to the packet then send it
                    //DO NOT SET THE SEND FLAG, this will handle it on its own since there could be multiple sends
                    if (!ferror(picture)){
                        response_p.seq_num = cur_seq_num;
                        cur_seq_num++;

                        response_p.length = (uint8_t)readSize;

                        //send this packet down to the data link layer
                        send_packet(pipes, response_p);
                    } else {
                        //an error occured return an error code so that the client can stop processing the image and drop the corrupt data
                        return_error(pipes, 1, &cur_seq_num);
                        break;
                    }
                }
                //close the picture that was being read
                fclose(picture);
                //delete the temporary file
                remove(filename);
            }
        }
    // Send it straight back
    //printf("APP:  Sending string of %d bytes:  %s\n", to_read, read_buffer);
    //write(pipe_write(pipes), read_buffer, to_read);
    }
    
    curr_clients--;
    pthread_exit(NULL);
}