Files @ 6e54cb7ffa00
Branch filter:

Location: DistRen/src/server/slavefuncs.c

ethanzonca@zserver2
Minor updates, added hostname to conf parser
/*
  Copyright 2009 Nathan Phillip Brink, Ethan Zonca, Matthew Orlando

  This file is a part of DistRen.

  DistRen is free software: you can redistribute it and/or modify
  it under the terms of the GNU Affero General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  DistRen is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU Affero General Public License for more details.

  You should have received a copy of the GNU Affero General Public License
  along with DistRen.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "asprintf.h"
#include "distrenjob.h"
#include "execio.h"
#include "protocol.h"
#include "remoteio.h"
#include "slavefuncs.h"

#include <curl/curl.h>
#include <curl/easy.h>
#include <curl/types.h>

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>


/**
   Sends the server a single request (see protocol.h)
*/
int sendSignal(struct remoteio *rem, char signal)
{
  size_t written;
  size_t towrite;
  char *ssignal;

  _distren_asprintf(&ssignal, "%c", signal);
  towrite = strlen(ssignal);
  while( towrite
	 && !remoteio_write(rem, ssignal, towrite, &written))
    {
      fprintf(stderr, "Writing...\n");
      towrite -= written;
    }
  if(written)
    return 0;

  /**
     if remoteio_write returned 1, the connection
     is probably dead or there was a real error
   */
  return 1;
}

/**
   Sends the server an extended signal (request + data)
*/
int sendExtSignal(struct remoteio *rem, char signal, char *data){
  size_t written;
  size_t towrite;
  char *ssignal;
  _distren_asprintf(&ssignal, "%c%s", signal, data); // Just append the data FIXME: We should do this differently
  towrite = strlen(ssignal);
  while( towrite
          && !remoteio_write(rem, ssignal, towrite, &written))
     {
       fprintf(stderr, "Writing...\n");
       towrite -= written;
     }
   if(written)
     return 0;

   /**
      if remoteio_write returned 1, the connection
      is probably dead or there was a real error
    */
   return 1;
}



/**
 utility function for XPath-ish stuff:
 */
xmlNodePtr xml_quickxpath(xmlXPathContextPtr xpathctxt, xmlChar *path)
{
  xmlNodePtr toreturn;

  xmlXPathObjectPtr xmlxpathobjptr;
  xmlxpathobjptr = xmlXPathEval(path, xpathctxt);
  if(!xmlxpathobjptr
     || !xmlxpathobjptr->nodesetval->nodeNr)
    {
      fprintf(stderr, "XPath resolution failed for ``%s'' in ``%s'' (``%s'')\n", path, xpathctxt->doc->name, xpathctxt->doc->URL);
      return (xmlNodePtr)NULL;
    }

  toreturn = *(xmlxpathobjptr->nodesetval->nodeTab);

  xmlXPathFreeObject(xmlxpathobjptr);

  return toreturn;
}


/** Stub for deleting job data from the disk. @TODO: unstubify me! */
int delete_jobdata(int jobnum, char *datadir)
{
  char *jobpath;
  _distren_asprintf(&jobpath, "%s/%d", datadir, jobnum);
  // rmdir(jobpath);
  fprintf(stderr, "Please manually remove %s. Automatic removal is currently not implemented.\n", jobpath);
  return 0;
}

/** Function referenced by curlget() to write data to disk. */
size_t curl_writetodisk(void *ptr, size_t size, size_t nmemb, FILE *stream)
 {
    return fwrite(ptr, size, nmemb, stream);
  }

/** Helper function for cURL's progress display */
int curl_progress( char *Bar,double t,double d,double ultotal,double ulnow)
{
fprintf(stderr,"Downloading: %f%% complete\r",d/t*100);
return 0;
}

/** Retrieves a URL with cURL and saves it to disk */
int curlget(char *url, char *out){
  fprintf(stderr,"Preparing to download %s",url);
  double *Bar; // Stores cURL progress display info
  CURL *curl;
  CURLcode res;
  FILE *outfile;

  curl = curl_easy_init();
  if(curl) {
	outfile = fopen(out, "w"); // Open where we're writing to

  curl_easy_setopt(curl, CURLOPT_URL, url);
  curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile);
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_writetodisk); // this MUST be set for win32 compat.
  curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
  curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, curl_progress);
  curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &Bar);
  res = curl_easy_perform(curl);
  curl_easy_cleanup(curl);
  }
  fprintf(stderr,"\n"); // Clears out he progressbar's carriage return
  return res; // 0 is OK, 1 is 404 or other error
}

/** Posts a file to a url with cUrl */
int curlpost(char *filename, char *url){
  char *targetname = "uploadedfile"; // Name of the target in the php file on the server (Don't change me unless you have different PHP code)
  CURL *curl;
  CURLcode res;
  struct curl_httppost *formpost=NULL;
  struct curl_httppost *lastptr=NULL;
  struct curl_slist *headerlist=NULL;
  static const char buf[] = "Expect:";

  curl_global_init(CURL_GLOBAL_ALL);

  /* upload field... */
  curl_formadd(&formpost,
               &lastptr,
               CURLFORM_COPYNAME, targetname,
               CURLFORM_FILE, filename,
               CURLFORM_END);
  /* filename field... */
  curl_formadd(&formpost,
               &lastptr,
               CURLFORM_COPYNAME, "filename",
               CURLFORM_COPYCONTENTS, filename,
               CURLFORM_END);
  /* submit field, not usually needed, just in case... */
  curl_formadd(&formpost,
               &lastptr,
               CURLFORM_COPYNAME, "submit",
               CURLFORM_COPYCONTENTS, "send",
               CURLFORM_END);

  curl = curl_easy_init();
  headerlist = curl_slist_append(headerlist, buf);
  if(curl) {
    /* Setting the URL to get the post, and the contents of the post */
    curl_easy_setopt(curl, CURLOPT_URL, url);
    curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
    res = curl_easy_perform(curl);

    curl_easy_cleanup(curl);
    /* cleanup the formpost junk */
    curl_formfree(formpost);
    curl_slist_free_all (headerlist);
  }
  return res;
}


/** Logs the user into the server after ensuring that keys exist */
int login_user(char *username)
{
  // @TODO: Put some telnet-style auth code here
  return 1; // success
}

/** Replaces wordtoreplace with replacewith in conffile (relative to SYSCONFDIR) */
int conf_replace(char *conffile, char *wordtoreplace, char *replacewith){
  int maxlinelen = 120;
  char *fileOrig;
  char *fileRepl;
  _distren_asprintf(&fileOrig, "&s&s", SYSCONFDIR, conffile);
  _distren_asprintf(&fileRepl, "&s&s.edited", SYSCONFDIR, conffile);
  char buffer[maxlinelen+2];
  char *buff_ptr, *find_ptr;
  FILE *fp1, *fp2;
  size_t find_len = strlen(wordtoreplace);
  fp1 = fopen(fileOrig,"r");
  fp2 = fopen(fileRepl,"w");
  if (fp1 ==NULL){
    fprintf(stderr, "%s doesn't exist\n",fileOrig);
    return 0;
  }
  else if(fp2 ==NULL){
    fprintf(stderr, "Can't write a file to disk! Check permissions.\n");
    return 0;
  }
  else{
    while(fgets(buffer,maxlinelen+2,fp1))
      {
        buff_ptr = buffer;
        while ((find_ptr = strstr(buff_ptr,wordtoreplace)))
        {
           while(buff_ptr < find_ptr)
             fputc((int)*buff_ptr++,fp2);
           fputs(replacewith,fp2);
           buff_ptr += find_len;
         }
         fputs(buff_ptr,fp2);
      }
    rename(fileRepl, fileOrig);
  }
  fclose(fp2);
  fclose(fp1);
  fprintf(stderr,"Wrote conf file...\n");
return 1; // Success
}


/* Executors */

/** Executor function for Blender operations */
int exec_blender(char *input, char *output, int frame)
{
  fprintf(stderr,"Preparing to execute...\n");
  int ret;
  char *frame_str;

  char *command = "blender"; // @TODO: We currently expect this to be in PATH
  char *cmd[] = { command, "-b", "-o", output, input, "-f", frame_str, (char *)NULL }; // arguments for blender

  char buf[10];
  struct execio *testrem;
  size_t readlen;

  _distren_asprintf(&frame_str, "%i", frame);

  fprintf(stderr,"Executing: %s\n", frame_str);
  ret = execio_open(&testrem, command, cmd);
  buf[9] = '\0';
  while(!execio_read(testrem, buf, 9, &readlen))
    {
      if(readlen > 9) {
        fprintf(stderr, "Something is terribly wrong!\n");
       }
       buf[readlen] = '\0';
       fprintf(stderr, "read \"%s\"\n", buf);
    }
  execio_close(testrem);

  return ret;
}

void xmlinit()
{
  xmlInitParser();
  xmlXPathInit();
}

void xmlcleanup()
{
  xmlCleanupParser();
}