Blame tests/benchmarks/bench_raw.c

Packit Service 31306d
/*
Packit Service 31306d
 * This file is part of the SSH Library
Packit Service 31306d
 *
Packit Service 31306d
 * Copyright (c) 2010 by Aris Adamantiadis
Packit Service 31306d
 *
Packit Service 31306d
 * The SSH Library is free software; you can redistribute it and/or modify
Packit Service 31306d
 * it under the terms of the GNU Lesser General Public License as published by
Packit Service 31306d
 * the Free Software Foundation; either version 2.1 of the License, or (at your
Packit Service 31306d
 * option) any later version.
Packit Service 31306d
 *
Packit Service 31306d
 * The SSH Library is distributed in the hope that it will be useful, but
Packit Service 31306d
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
Packit Service 31306d
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
Packit Service 31306d
 * License for more details.
Packit Service 31306d
 *
Packit Service 31306d
 * You should have received a copy of the GNU Lesser General Public License
Packit Service 31306d
 * along with the SSH Library; see the file COPYING.  If not, write to
Packit Service 31306d
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
Packit Service 31306d
 * MA 02111-1307, USA.
Packit Service 31306d
 */
Packit Service 31306d
Packit Service 31306d
#include "benchmarks.h"
Packit Service 31306d
#include <string.h>
Packit Service 31306d
#include <stdlib.h>
Packit Service 31306d
#include <stdio.h>
Packit Service 31306d
Packit Service 31306d
#define PYTHON_PATH "/usr/bin/python"
Packit Service 31306d
Packit Service 31306d
const char python_eater[]=
Packit Service 31306d
"#!/usr/bin/python\n"
Packit Service 31306d
"import sys\n"
Packit Service 31306d
"print 'go'\n"
Packit Service 31306d
"sys.stdout.flush()\n"
Packit Service 31306d
"toread=XXXXXXXXXX\n"
Packit Service 31306d
"read=0\n"
Packit Service 31306d
"while(read < toread):\n"
Packit Service 31306d
"    buffersize=toread-read\n"
Packit Service 31306d
"    if(buffersize > 4096):\n"
Packit Service 31306d
"        buffersize=4096\n"
Packit Service 31306d
"    r=len(sys.stdin.read(buffersize))\n"
Packit Service 31306d
"    read+=r\n"
Packit Service 31306d
"    if(r<=0):\n"
Packit Service 31306d
"        print 'error'\n"
Packit Service 31306d
"        exit()\n"
Packit Service 31306d
"print 'done'\n";
Packit Service 31306d
Packit Service 31306d
static char *get_python_eater(unsigned long bytes){
Packit Service 31306d
  char *eater=malloc(sizeof(python_eater));
Packit Service 31306d
  char *ptr;
Packit Service 31306d
  char buf[12];
Packit Service 31306d
Packit Service 31306d
  memcpy(eater,python_eater,sizeof(python_eater));
Packit Service 31306d
  ptr=strstr(eater,"XXXXXXXXXX");
Packit Service 31306d
  if(!ptr){
Packit Service 31306d
    free(eater);
Packit Service 31306d
    return NULL;
Packit Service 31306d
  }
Packit Service 31306d
  sprintf(buf,"0x%.8lx",bytes);
Packit Service 31306d
  memcpy(ptr,buf,10);
Packit Service 31306d
  return eater;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/** @internal
Packit Service 31306d
 * @brief uploads a script (python or other) at a specific path on the
Packit Service 31306d
 * remote host
Packit Service 31306d
 * @param[in] session an active SSH session
Packit Service 31306d
 * @param[in] path to copy the file
Packit Service 31306d
 * @param[in] content of the file to copy
Packit Service 31306d
 * @return 0 on success, -1 on error
Packit Service 31306d
 */
Packit Service 31306d
static int upload_script(ssh_session session, const char *path,
Packit Service 31306d
    const char *script){
Packit Service 31306d
  ssh_channel channel;
Packit Service 31306d
  char cmd[128];
Packit Service 31306d
  int err;
Packit Service 31306d
Packit Service 31306d
  channel=ssh_channel_new(session);
Packit Service 31306d
  if(!channel)
Packit Service 31306d
    goto error;
Packit Service 31306d
  if(ssh_channel_open_session(channel) == SSH_ERROR)
Packit Service 31306d
    goto error;
Packit Service 31306d
  snprintf(cmd,sizeof(cmd),"cat > %s",path);
Packit Service 31306d
  if(ssh_channel_request_exec(channel,cmd) == SSH_ERROR)
Packit Service 31306d
    goto error;
Packit Service 31306d
  err=ssh_channel_write(channel,script,strlen(script));
Packit Service 31306d
  if(err == SSH_ERROR)
Packit Service 31306d
    goto error;
Packit Service 31306d
  if(ssh_channel_send_eof(channel) == SSH_ERROR)
Packit Service 31306d
    goto error;
Packit Service 31306d
  if(ssh_channel_close(channel) == SSH_ERROR)
Packit Service 31306d
    goto error;
Packit Service 31306d
  ssh_channel_free(channel);
Packit Service 31306d
  return 0;
Packit Service 31306d
error:
Packit Service 31306d
  fprintf(stderr,"Error while copying script : %s\n",ssh_get_error(session));
Packit Service 31306d
  return -1;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/** @internal
Packit Service 31306d
 * @brief benchmarks a raw upload (simple upload in a SSH channel) using an
Packit Service 31306d
 * existing SSH session.
Packit Service 31306d
 * @param[in] session Open SSH session
Packit Service 31306d
 * @param[in] args Parsed command line arguments
Packit Service 31306d
 * @param[out] bps The calculated bytes per second obtained via benchmark.
Packit Service 31306d
 * @return 0 on success, -1 on error.
Packit Service 31306d
 */
Packit Service 31306d
int benchmarks_raw_up (ssh_session session, struct argument_s *args,
Packit Service 31306d
    float *bps){
Packit Service 31306d
  unsigned long bytes;
Packit Service 31306d
  char *script;
Packit Service 31306d
  char cmd[128];
Packit Service 31306d
  int err;
Packit Service 31306d
  ssh_channel channel;
Packit Service 31306d
  struct timestamp_struct ts;
Packit Service 31306d
  float ms=0.0;
Packit Service 31306d
  unsigned long total=0;
Packit Service 31306d
Packit Service 31306d
  bytes = args->datasize * 1024 * 1024;
Packit Service 31306d
  script =get_python_eater(bytes);
Packit Service 31306d
  err=upload_script(session,"/tmp/eater.py",script);
Packit Service 31306d
  free(script);
Packit Service 31306d
  if(err<0)
Packit Service 31306d
    return err;
Packit Service 31306d
  channel=ssh_channel_new(session);
Packit Service 31306d
  if(channel == NULL)
Packit Service 31306d
    goto error;
Packit Service 31306d
  if(ssh_channel_open_session(channel)==SSH_ERROR)
Packit Service 31306d
    goto error;
Packit Service 31306d
  snprintf(cmd,sizeof(cmd),"%s /tmp/eater.py", PYTHON_PATH);
Packit Service 31306d
  if(ssh_channel_request_exec(channel,cmd)==SSH_ERROR)
Packit Service 31306d
    goto error;
Packit Service 31306d
  if((err=ssh_channel_read(channel,buffer,sizeof(buffer)-1,0))==SSH_ERROR)
Packit Service 31306d
    goto error;
Packit Service 31306d
  buffer[err]=0;
Packit Service 31306d
  if(!strstr(buffer,"go")){
Packit Service 31306d
    fprintf(stderr,"parse error : %s\n",buffer);
Packit Service 31306d
    ssh_channel_close(channel);
Packit Service 31306d
    ssh_channel_free(channel);
Packit Service 31306d
    return -1;
Packit Service 31306d
  }
Packit Service 31306d
  if(args->verbose>0)
Packit Service 31306d
    fprintf(stdout,"Starting upload of %lu bytes now\n",bytes);
Packit Service 31306d
  timestamp_init(&ts);
Packit Service 31306d
  while(total < bytes){
Packit Service 31306d
    unsigned long towrite = bytes - total;
Packit Service 31306d
    int w;
Packit Service 31306d
    if(towrite > args->chunksize)
Packit Service 31306d
      towrite = args->chunksize;
Packit Service 31306d
    w=ssh_channel_write(channel,buffer,towrite);
Packit Service 31306d
    if(w == SSH_ERROR)
Packit Service 31306d
      goto error;
Packit Service 31306d
    total += w;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  if(args->verbose>0)
Packit Service 31306d
    fprintf(stdout,"Finished upload, now waiting the ack\n");
Packit Service 31306d
Packit Service 31306d
  if((err=ssh_channel_read(channel,buffer,5,0))==SSH_ERROR)
Packit Service 31306d
      goto error;
Packit Service 31306d
  buffer[err]=0;
Packit Service 31306d
  if(!strstr(buffer,"done")){
Packit Service 31306d
    fprintf(stderr,"parse error : %s\n",buffer);
Packit Service 31306d
    ssh_channel_close(channel);
Packit Service 31306d
    ssh_channel_free(channel);
Packit Service 31306d
    return -1;
Packit Service 31306d
  }
Packit Service 31306d
  ms=elapsed_time(&ts);
Packit Service 31306d
  *bps=8000 * (float)bytes / ms;
Packit Service 31306d
  if(args->verbose > 0)
Packit Service 31306d
    fprintf(stdout,"Upload took %f ms for %lu bytes, at %f bps\n",ms,
Packit Service 31306d
        bytes,*bps);
Packit Service 31306d
  ssh_channel_close(channel);
Packit Service 31306d
  ssh_channel_free(channel);
Packit Service 31306d
  return 0;
Packit Service 31306d
error:
Packit Service 31306d
  fprintf(stderr,"Error during raw upload : %s\n",ssh_get_error(session));
Packit Service 31306d
  if(channel){
Packit Service 31306d
    ssh_channel_close(channel);
Packit Service 31306d
    ssh_channel_free(channel);
Packit Service 31306d
  }
Packit Service 31306d
  return -1;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
const char python_giver[] =
Packit Service 31306d
"#!/usr/bin/python\n"
Packit Service 31306d
"import sys\n"
Packit Service 31306d
"r=sys.stdin.read(2)\n"
Packit Service 31306d
"towrite=XXXXXXXXXX\n"
Packit Service 31306d
"wrote=0\n"
Packit Service 31306d
"mtu = 32786\n"
Packit Service 31306d
"buf = 'A'*mtu\n"
Packit Service 31306d
"while(wrote < towrite):\n"
Packit Service 31306d
"    buffersize=towrite-wrote\n"
Packit Service 31306d
"    if(buffersize > mtu):\n"
Packit Service 31306d
"        buffersize=mtu\n"
Packit Service 31306d
"    if(buffersize == mtu):\n"
Packit Service 31306d
"        sys.stdout.write(buf)\n"
Packit Service 31306d
"    else:\n"
Packit Service 31306d
"        sys.stdout.write('A'*buffersize)\n"
Packit Service 31306d
"    wrote+=buffersize\n"
Packit Service 31306d
"sys.stdout.flush()\n";
Packit Service 31306d
Packit Service 31306d
static char *get_python_giver(unsigned long bytes){
Packit Service 31306d
  char *giver=malloc(sizeof(python_giver));
Packit Service 31306d
  char *ptr;
Packit Service 31306d
  char buf[12];
Packit Service 31306d
Packit Service 31306d
  memcpy(giver,python_giver,sizeof(python_giver));
Packit Service 31306d
  ptr=strstr(giver,"XXXXXXXXXX");
Packit Service 31306d
  if(!ptr){
Packit Service 31306d
    free(giver);
Packit Service 31306d
    return NULL;
Packit Service 31306d
  }
Packit Service 31306d
  sprintf(buf,"0x%.8lx",bytes);
Packit Service 31306d
  memcpy(ptr,buf,10);
Packit Service 31306d
  return giver;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/** @internal
Packit Service 31306d
 * @brief benchmarks a raw download (simple upload in a SSH channel) using an
Packit Service 31306d
 * existing SSH session.
Packit Service 31306d
 * @param[in] session Open SSH session
Packit Service 31306d
 * @param[in] args Parsed command line arguments
Packit Service 31306d
 * @param[out] bps The calculated bytes per second obtained via benchmark.
Packit Service 31306d
 * @return 0 on success, -1 on error.
Packit Service 31306d
 */
Packit Service 31306d
int benchmarks_raw_down (ssh_session session, struct argument_s *args,
Packit Service 31306d
    float *bps){
Packit Service 31306d
  unsigned long bytes;
Packit Service 31306d
  char *script;
Packit Service 31306d
  char cmd[128];
Packit Service 31306d
  int err;
Packit Service 31306d
  ssh_channel channel;
Packit Service 31306d
  struct timestamp_struct ts;
Packit Service 31306d
  float ms=0.0;
Packit Service 31306d
  unsigned long total=0;
Packit Service 31306d
Packit Service 31306d
  bytes = args->datasize * 1024 * 1024;
Packit Service 31306d
  script =get_python_giver(bytes);
Packit Service 31306d
  err=upload_script(session,"/tmp/giver.py",script);
Packit Service 31306d
  free(script);
Packit Service 31306d
  if(err<0)
Packit Service 31306d
    return err;
Packit Service 31306d
  channel=ssh_channel_new(session);
Packit Service 31306d
  if(channel == NULL)
Packit Service 31306d
    goto error;
Packit Service 31306d
  if(ssh_channel_open_session(channel)==SSH_ERROR)
Packit Service 31306d
    goto error;
Packit Service 31306d
  snprintf(cmd,sizeof(cmd),"%s /tmp/giver.py", PYTHON_PATH);
Packit Service 31306d
  if(ssh_channel_request_exec(channel,cmd)==SSH_ERROR)
Packit Service 31306d
    goto error;
Packit Service 31306d
  if((err=ssh_channel_write(channel,"go",2))==SSH_ERROR)
Packit Service 31306d
    goto error;
Packit Service 31306d
  if(args->verbose>0)
Packit Service 31306d
    fprintf(stdout,"Starting download of %lu bytes now\n",bytes);
Packit Service 31306d
  timestamp_init(&ts);
Packit Service 31306d
  while(total < bytes){
Packit Service 31306d
    unsigned long toread = bytes - total;
Packit Service 31306d
    int r;
Packit Service 31306d
    if(toread > args->chunksize)
Packit Service 31306d
      toread = args->chunksize;
Packit Service 31306d
    r=ssh_channel_read(channel,buffer,toread,0);
Packit Service 31306d
    if(r == SSH_ERROR)
Packit Service 31306d
      goto error;
Packit Service 31306d
    total += r;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  if(args->verbose>0)
Packit Service 31306d
    fprintf(stdout,"Finished download\n");
Packit Service 31306d
  ms=elapsed_time(&ts);
Packit Service 31306d
  *bps=8000 * (float)bytes / ms;
Packit Service 31306d
  if(args->verbose > 0)
Packit Service 31306d
    fprintf(stdout,"Download took %f ms for %lu bytes, at %f bps\n",ms,
Packit Service 31306d
        bytes,*bps);
Packit Service 31306d
  ssh_channel_close(channel);
Packit Service 31306d
  ssh_channel_free(channel);
Packit Service 31306d
  return 0;
Packit Service 31306d
error:
Packit Service 31306d
  fprintf(stderr,"Error during raw upload : %s\n",ssh_get_error(session));
Packit Service 31306d
  if(channel){
Packit Service 31306d
    ssh_channel_close(channel);
Packit Service 31306d
    ssh_channel_free(channel);
Packit Service 31306d
  }
Packit Service 31306d
  return -1;
Packit Service 31306d
}