Changeset - 0fa8dda72d6a
[Not reviewed]
default
0 3 0
Nathan Brink (binki) - 15 years ago 2010-08-09 23:20:05
ohnobinki@ohnopublishing.net
Working job unpacking.
3 files changed with 42 insertions and 24 deletions:
0 comments (0 inline, 0 general)
src/server/distrend.c
Show inline comments
 
@@ -69,48 +69,51 @@ struct general_info
 
     */
 
    char *userlist;
 

	
 
    /**
 
     * where to store in-progress uploads or things that should
 
     * otherwise be on the same filesystem as the rest of the datadir
 
     * so that it may be rename()d.
 
     */
 
    char *tmpdir;
 
    
 
  } files;
 

	
 
  int jobs_in_queue;
 
  unsigned int free_clients;
 
  unsigned int rendering_clients;
 
  unsigned int total_finished_jobs;
 
  unsigned int total_frames_rendered;
 
  unsigned int highest_jobnum;
 
  int hibernate;
 
  time_t timestamp;
 
  unsigned long total_render_power;
 
  unsigned long total_priority_pieces;
 

	
 
  user_mgr_t user_mgr;
 

	
 
  /* my servertype, see protocol.h */
 
  uint8_t servertype;
 
};
 

	
 

	
 
/* *********************************************
 
   Function Prototypes
 
   ********************************************* */
 

	
 
/* ************General Functions************* */
 
int distrend_do();
 
int distrend_do_config(int argc, char *argv[], struct distrend_config **config, multiio_context_t multiio);
 
int distrend_config_free(struct distrend_config *config);
 
int distrend_handle_request(struct distrend_listens *listens, struct distrend_client *client, struct distren_request *req, void *reqdata, struct general_info *geninfo);
 

	
 
/**
 
 * client request handlers
 
 */
 
int distrend_handle_version(struct general_info *geninfo, struct distrend_client *client, struct distren_request *req, void *req_data);
 
int distrend_handle_pass(struct general_info *geninfo, struct distrend_client *client, struct distren_request *req, void *req_data);
 
int distrend_handle_file_post_start(struct general_info *geninfo, struct distrend_client *client, struct distren_request *req, void *req_data);
 
int distrend_handle_file_post(struct general_info *geninfo, struct distrend_client *client, struct distren_request *req, void *req_data);
 
int distrend_handle_file_post_finish(struct general_info *geninfo, struct distrend_client *client, struct distren_request *req, void *req_data);
 

	
 
/* functions of some generic sort ...ish */
 
int distrend_handle_successful_upload(struct distrend_client *client, struct distrend_client_file_post *client_file_post);
 
@@ -286,48 +289,50 @@ int distrend_handle_version(struct gener
 
       * Now we will mark the client as valid.
 
       *
 
       * We won't increment his time to live, though, because it shouldn't take
 
       * him that long to auth.
 
       */
 
      client->state = DISTREND_CLIENT_PREAUTH;
 
    }
 
  else
 
    {
 
      /**
 
       * The client claims to be of a different version of distren.
 
       * Now we will just send a disconnect packet and disconnect the client.
 
       */
 
      _distren_asprintf(&tmp_str, "You have tried to connect to a %s server when your client claims to be running %s. Bye ;-)\n", PACKAGE_STRING, version.package_string);
 
      if(tmp_str)
 
	{
 
	  distrend_send_disconnect(client, tmp_str);
 
	  free(tmp_str);
 
	}
 
      else
 
	distrend_send_disconnect(client, "Invalid PACKAGE_VERSION :-|.");
 
      return 1;
 
    }
 

	
 
  client->servertype = version.servertype;
 

	
 
  return 0;
 
}
 

	
 
/**
 
 * Handle a DISTREN_REQUEST_PASS request.
 
 */
 
int distrend_handle_pass(struct general_info *geninfo, struct distrend_client *client, struct distren_request *req, void *req_data)
 
{
 
  struct distren_request_pass *pass_req;
 

	
 
  char username[DISTREN_REQUEST_PASS_USERNAME_LEN + 1];
 
  char pass[DISTREN_REQUEST_PASS_PASS_LEN + 1];
 

	
 
  struct user *user;
 

	
 
  if(req->len < sizeof(struct distren_request_pass))
 
    {
 
      distrend_send_disconnect(client, "You tried to send too short of a DISTREN_REQUEST_PASS.");
 
      return 1;
 
    }
 

	
 
  pass_req = req_data;
 
  memcpy(username, pass_req->username, DISTREN_REQUEST_PASS_USERNAME_LEN);
 
  username[DISTREN_REQUEST_PASS_USERNAME_LEN] = '\0';
 
@@ -373,73 +378,69 @@ struct distrend_client_file_post *distre
 
/**
 
 * Finds a post_context based on the post_id and client.
 
 *
 
 * Compatible the distren_request_parse_file_post_find_context_func_t.
 
 */
 
static distren_request_file_post_context_t distrend_client_find_file_post_context(uint32_t post_id, void *client)
 
{
 
  struct distrend_client_file_post *client_file_post;
 

	
 
  client_file_post = distrend_client_find_post(client, post_id);
 
  if(client_file_post)
 
    return client_file_post->post_context;
 
  return NULL;
 
}
 

	
 
/**
 
 * Clean up and free a client_file_post
 
 *
 
 * Whenever calling this functino, you almost _always_ have to call
 
 * list_remove_element(client->file_post_list, client_file_post);
 
 * first.
 
 */
 
void distrend_client_file_post_free(struct distrend_client_file_post *client_file_post)
 
{
 
  fclose(client_file_post->fd);
 
  if(client_file_post->fd)
 
    fclose(client_file_post->fd);
 
  free(client_file_post->filename);
 
  unlink(client_file_post->file_save_path);
 
  free(client_file_post->file_save_path);
 

	
 
  free(client_file_post);
 
}
 

	
 
int distrend_handle_file_post_start(struct general_info *geninfo, struct distrend_client *client, struct distren_request *req, void *req_data)
 
{
 
  struct distrend_client_file_post *client_file_post;
 

	
 
  distren_request_file_post_context_t post_context;
 
  uint32_t post_id;
 
  char *filename;
 

	
 
  char *str_tmp;
 

	
 
  int ret;
 

	
 
  /**
 
   * @todo access check!
 
   */
 
  fprintf(stderr, __FILE__ ":%d:distrend_handle_file_post_start(): You need to check if a client is actually allowed to upload files somehow!\n", __LINE__);
 

	
 
  /*
 
   * other servers should be excluded from this check, but we don't
 
   * store the servertype in client yet.
 
   */
 
  if(list_size(client->file_post_list) > 1)
 
    {
 
      distrend_send_disconnect(client, "You are trying to upload too many files at once!");
 
      return 1;
 
    }
 

	
 
  ret = distren_request_parse_file_post_start(req, req_data, &post_context, &post_id, &filename);
 
  if(ret)
 
    {
 
      distrend_send_disconnect(client, "You sent me an invalid DISTREN_REQUEST_FILE_POST_START packet");
 
      return 1;
 
    }
 

	
 
  if(distrend_client_find_post(client, post_id))
 
    {
 
      _distren_asprintf(&str_tmp, "Err accepting file: You are trying to upload using post_id=%d while you have already started another upload using the same post_id", post_id);
 
      distrend_send_disconnect(client, str_tmp);
 
      free(str_tmp);
 

	
 
      distren_request_file_post_context_free(post_context);
 
@@ -560,66 +561,70 @@ int distrend_handle_file_post_finish(str
 
	  /* checksuming failed */
 
	  distrend_send_disconnect(client, "You have uploaded a file that doesn't match its checksum somehow... which should be pretty much impossible");
 
	  client_file_post = distrend_client_find_post(client, post_id);
 
	  if(client_file_post)
 
	    {
 
	      list_remove_element(client->file_post_list, client_file_post);
 
	      distrend_client_file_post_free(client_file_post);
 
	    }
 
	  return 1;
 

	
 
	default:
 
	  distrend_send_disconnect(client, "You sent me an invalid DISTREN_REQUEST_FILE_POST_FINISH packet");
 
	}
 
      return 1;
 
    }
 

	
 
  client_file_post = distrend_client_find_post(client, post_id);
 
  if(!client_file_post)
 
    return 1;
 

	
 
  /*
 
   * Here it is... manage a file being submitted for rendering... or
 
   * for whatever purpose it was uploaded for somehow...
 
   */
 
  fclose(client_file_post->fd);
 
  client_file_post->fd = NULL;
 
  distrend_handle_successful_upload(client, client_file_post);
 

	
 
  list_remove_element(client->file_post_list, client_file_post);
 
  distrend_client_file_post_free(client_file_post);
 

	
 
  return 0;
 
}
 

	
 
/**
 
 * Does stuff with file uploads after they've been successfully acquired.
 
 *
 
 * @todo this should probably be genericized to handle 1. file uploads and 2. server-initiated file _downloads_, i.e., using libcurl. In that case, struct distrend_client_file_post shouldn't be passed directly to ourself but some common struct might be passed here.
 
 */
 
int distrend_handle_successful_upload(struct distrend_client *client, struct distrend_client_file_post *client_file_post)
 
{
 
  fprintf(stderr, __FILE__ ":%d: STUB: I don't know what to do with %s[%s] :-/\n", __LINE__,
 
	  client_file_post->filename, client_file_post->file_save_path);
 

	
 
  unpackJob("/home/ohnobinki/var/distren/tmp", client_file_post->file_save_path);
 

	
 
  return 0;
 
}
 

	
 
/**
 
   Performs command stored in a client's request. @TODO: Fill stub
 
*/
 
int distrend_do()
 
{
 
  return 0;
 
}
 

	
 
/* Grabs config info from confs */
 
int distrend_do_config(int argc, char *argv[], struct distrend_config **config, multiio_context_t multiio)
 
{
 
  unsigned int counter;
 

	
 
  cfg_opt_t myopts_listen[] =
 
    {
 
      CFG_SIMPLE_STR("type", NULL),
 
      CFG_SIMPLE_STR("path", NULL),
 
      CFG_SIMPLE_INT("port", NULL),
 
      CFG_END()
 
    };
 
  cfg_opt_t myopts[] =
src/server/listen.h
Show inline comments
 
@@ -108,48 +108,53 @@ struct distrend_listens
 
  */
 
  multiio_socket_type_t socket_type;
 
};
 

	
 
struct distrend_client_file_post
 
{
 
  distren_request_file_post_context_t post_context;
 
  uint32_t post_id;
 
  /** user-friendly filename */
 
  char *filename;
 
  /** on-disk filename */
 
  char *file_save_path;
 
  FILE *fd;
 
};
 

	
 
/**
 
   The information necessary to recieve data from and send data
 
   to a client.
 
 */
 
struct distrend_client
 
{
 
  enum distrend_client_state state;
 

	
 
  /**
 
   * \see protocol.h for DISTREN_SERVERTYPE_ constants.
 
   */
 
  uint8_t servertype;
 

	
 
  /**
 
     The absolute time at which this client's entry in the client list will be
 
     expired, closed, and marked as dead so that it may be cleaned up. This is
 
     used to implement ping timeouts (if state == DISTREND_CLIENT_GOOD) and 
 
     disconnect message grace time (if state == DISTREND_CLIENT_BAD).
 
   */
 
  time_t cleanup_time;
 

	
 
  size_t inlen; /*< number of bytes waiting to be processed */
 
  size_t expectlen; /*< number of bytes that inlen has to be for a complete request to be had, 0 when waiting on header */
 

	
 
  struct tabletennis_client tabletennis_client;
 

	
 
  /**
 
   * File postings (uploads) are per-connection, and thus stored
 
   * here. Of type struct distrend_client_file_post.
 
   */
 
  list_t file_post_list;
 

	
 
  /**
 
   * Yes, in some places we need a unique key for this connection.
 
   */
 
  int connection_id;
 

	
 
  /**
src/server/slavefuncs.c
Show inline comments
 
@@ -790,72 +790,80 @@ free(realOutput);
 
   @param pathtoTar filename of the archive to extract
 

	
 
   ohnobinki: please make me work :-\
 
 */
 
int unpackJob(char *outdir, char *pathtoTar)
 
{
 
  int ret;
 

	
 
  struct archive *a;
 
  struct archive_entry *ae;
 
  int astatus;
 

	
 
  /* ignore return because directory may exist already */
 
  mkdir(outdir, 0700);
 
  ret = chdir(outdir);
 
  if(ret == -1)
 
    {
 
      perror("chdir");
 
      return 1;
 
    }
 

	
 
  a = archive_read_new();
 
  ae = archive_entry_new();
 

	
 
  archive_read_support_compression_all(a);
 
  archive_read_support_format_raw(a);
 
  astatus = archive_read_open_filename(a, pathtoTar, 8192);
 
  if (astatus != ARCHIVE_OK)
 
  if(!a
 
     || !ae)
 
    {
 
      fprintf(stderr, "Error opening archive!\n");
 
      if(a)
 
	archive_read_finish(a);
 
      if(ae)
 
	archive_entry_free(ae);
 
      return 1;
 
    }
 

	
 
  for(astatus = ARCHIVE_OK;
 
      astatus == ARCHIVE_OK
 
        || astatus == ARCHIVE_WARN;
 
      )
 
  fprintf(stderr, "Trying to unpack %s into %s\n", pathtoTar, outdir);
 

	
 
  archive_read_support_compression_all(a);
 
  archive_read_support_format_all(a);
 
  astatus = archive_read_open_filename(a, pathtoTar, 1);
 
  if (astatus != ARCHIVE_OK)
 
    {
 
      astatus = archive_read_next_header2(a, ae);
 
      if(astatus == ARCHIVE_WARN)
 
        fprintf(stderr, "Encountered nonfatal read error somehow!\n");
 
      fprintf(stderr, "Error opening archive!\n");
 
      archive_read_finish(a);
 
      archive_entry_free(ae);
 
      return 1;
 
    }
 

	
 
      if(astatus == ARCHIVE_OK
 
         || astatus == ARCHIVE_WARN)
 
        astatus = archive_read_extract(a, ae,
 
                                       ARCHIVE_EXTRACT_NO_OVERWRITE
 
                                       | ARCHIVE_EXTRACT_SECURE_SYMLINKS
 
                                       | ARCHIVE_EXTRACT_SECURE_NODOTDOT);
 
  while((astatus = archive_read_next_header2(a, ae)) == ARCHIVE_OK)
 
    {
 
      astatus = archive_read_extract(a, ae,
 
				     ARCHIVE_EXTRACT_NO_OVERWRITE
 
				     | ARCHIVE_EXTRACT_SECURE_SYMLINKS
 
				     | ARCHIVE_EXTRACT_SECURE_NODOTDOT);
 
      if(astatus != ARCHIVE_OK)
 
	fprintf(stderr, "Encountered error or warning when attempting to extract file: %s\n",
 
		archive_entry_pathname(ae));
 
    }
 
  archive_entry_free(ae);
 
  archive_read_finish(a);
 

	
 
  if(astatus != ARCHIVE_EOF)
 
    {
 
      fprintf(stderr, "Error reading archive!\n");
 
      return 1;
 
    }
 

	
 
  return 0;
 
}
 

	
 

	
 
/** Logs the user into the server after ensuring that keys exist
 
    ohnobinki: I assume you could use this for remoteio, or just kill it
 
*/
 
int login_user(char *username)
 
{
 
  // @TODO: Put some telnet-style auth code here unless this is obselete
 
  return 1; // success
 
}
 

	
 
/**
0 comments (0 inline, 0 general)