Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Лабы / 3 / 2.tar / 2 / 2 / net_copy / uthreads

.cpp
Скачиваний:
16
Добавлен:
17.04.2013
Размер:
7.28 Кб
Скачать
/*
  netFileCopyer
  Copyright (C) 2004 Dmitry S. Vasilchenko.

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

  This program 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 General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

  The GNU GPL is contained in /usr/doc/copyright/GPL on a Debian
  system and in the file COPYING in the Linux kernel source.
*/

#include <stdlib.h>

#include <qapplication.h>
#include <qthread.h>
#include <qtextcodec.h>

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

#include "uthreads.h"
#include "os_spec.h"
#include "ftransfer.h"

ThMain::ThMain()
	:QThread()
{
	stopped = false;	
}

void ThMain::setParams(const QString &pip, const int pport,
		const QString &pfile, const int pstate)
{
	ip = pip;
	port = pport;
	file = pfile;
	state = pstate;
	
	oi = NULL;
}

void ThMain::stop()
{
	if (oi) oi->d_stop();
	stopped = true;
}

QString ThMain::oi_last_error()
{
	if (oi)
		return oi->get_last_error();
	else
		return QString("oi not created");
}

int ThMain::oi_estate()
{
	if (oi)
		return oi->estate();
	else
		return 0;
}

/* SEND-RECEIVE THREAD */
void ThMain::run()
{
	unsigned char dack;

	size_t count = 0, ntrans = 0;
	size_t BSIZE = 8192; /* block size for transfer */
	fd = -1;
	char *buff = (char *)malloc(sizeof(char)*BSIZE);
	
	unsigned int len = 0; /* file name length */
	
	start_time = 0;
	file_size = 0;
	file_progress = 0;
	stage = STAGE_PRE;
		
/* SEND THREAD */
if (state == S_SEND){
	QTextCodec *codec = QTextCodec::codecForName("KOI8-R");
	QString ttfile = codec->fromUnicode( file );
	file_size = get_fsize(ttfile.ascii());

	/* extract file name from file path */
	int p = file.length()-1;
	while (p != -1 && file[p] != '/' && file[p] != '\\') p--;
	file_name = file.right(file.length() - p - 1);

	
	stage = STAGE_CONNECT;
	while (!stopped){
		((FTransferDialog *)pdialog)->stateUpdate(stage, file_size,
					file_progress, start_time, file_name);
		
		/* CONNECT */
		/* open socket, connect & send info about file name and size */
		if (stage == STAGE_CONNECT){
			
			/* SOCKET */
			oi = new oi_connect();
			if (oi->estate()){ 
				stage = STAGE_ERROR; continue;
			}

			/* CONNECT */
			if (oi->d_connect(ip.ascii(), port) < 0){ 
				stage = STAGE_ERROR; continue;
			}

			/* Connection established! */
			start_time = time(NULL); /* transfer start time */
			((FTransferDialog *)pdialog)->start_transfer = true;


			/* SENDINFO */
			/* send some innformation about file name and size */

			/* file_size */
			if (oi->d_send(&file_size, sizeof(file_size)) < 0){
				stage = STAGE_ERROR; continue;
			}
			/* file name length */
			QString tfile = codec->fromUnicode( file_name );
			len = tfile.length();
			if (oi->d_send(&len, sizeof(len)) < 0){
				stage = STAGE_ERROR; continue;
			}
			/* file name */
			if (oi->d_send(tfile.ascii(), len*sizeof(char)) < 0){
				stage = STAGE_ERROR; continue;
			}

			/* WAIT_ACK */
			/* after send information about file name and size
		 	 * we should wait for reply from remote machine */
			if (oi->d_recv(&dack, sizeof(dack)) < 0){
				stage = STAGE_ERROR; continue;
			}
			
			stage = STAGE_SENDFILE;
		}

		/* SENDFILE */
		/* now we can start transfer file */
		else if (stage == STAGE_SENDFILE){
			if (fd < 0){ /* open file for reading */
				QTextCodec *codec = QTextCodec::codecForName("KOI8-R");
				QString tfile = codec->fromUnicode( file );
				fd = open(tfile.ascii(),O_RDONLY);
				if (fd < 0){
					stage = STAGE_ERFOPEN; continue;
				}
			}
			/* transfer *BSIZE* byte each time */
			count = file_size - file_progress;
			count = (count > BSIZE) ? BSIZE : count;
			
			/* read next block from file */
			ntrans = read(fd, buff, sizeof(char)*count);
			if (ntrans != count*sizeof(char)){
				stage = STAGE_ERFREAD; continue;
			}
			
			/* send block to remote machine */
			if (oi->d_send(buff, sizeof(char)*count)<0){
				stage = STAGE_ERROR; continue;
			}

			/* wait for confirmation */
			if (oi->d_recv(&dack, sizeof(dack))<0){
				stage = STAGE_ERROR; continue;
			}
			file_progress += count;
			if (file_progress == file_size) /* all file transfered */
				stage = STAGE_FINISH;
		}
		
		else if (stage == STAGE_FINISH){
			stopped = true;
		}
		else{ /* error! */
			stopped = true;			
		}
	}
}
/* RECEIVE THREAD */
else if (state == S_RECEIVE){
	
	stage = STAGE_ACCEPT;
	while (!stopped){
		((FTransferDialog *)pdialog)->stateUpdate(stage, file_size,
				file_progress, start_time, file_name);
		
		/* ACCEPT */
		/* open socket, wait for remote connection, and
		 * when receive information about file name and size */
		if (stage == STAGE_ACCEPT){

			/* SOCKET */
			oi = new oi_connect();
			if (oi->estate()){ 
				stage = STAGE_ERROR; continue;
			}

			/* accept connection */
			if ( oi->d_accept(port) < 0){ 
				stage = STAGE_ERROR; continue;
			}

			/* Connection established! */
			start_time = time(NULL);
			((FTransferDialog *)pdialog)->start_transfer = true;
			
			/* GETINFO */
			/* receive information about file name and size */
			/* file_size */
			if (oi->d_recv(&file_size, sizeof(file_size)) < 0){
				stage = STAGE_ERROR; continue;
			}
			/* file name length */
			
			if (oi->d_recv(&len, sizeof(len)) < 0){
				stage = STAGE_ERROR; continue;
			}
			/* file name */
			char *str = (char *)malloc(sizeof(char)*(len+1));
			if (oi->d_recv(str, len*sizeof(char)) < 0){
				stage = STAGE_ERROR; continue;
			}
			str[len] = '\0';
			
			file_name = str;
			QTextCodec *codec = QTextCodec::codecForName("KOI8-R");
			file_name = codec->toUnicode( file_name );
			if (file[file.length()-1] == '/')
				file = file + file_name;
			else
				file = file + "/" + file_name;
			free(str);

			if (oi->d_send(&dack,sizeof(dack)) < 0){
				stage = STAGE_ERROR; continue;
			}
			
			stage = STAGE_RECEIVEFILE;
		}

		/* RECEIVE FILE */
		else if (stage == STAGE_RECEIVEFILE){ /* now receive file */
			if (fd < 0){
				fd = open(file.ascii(), O_WRONLY | O_CREAT, 0666);
				if (fd < 0){
					stage = STAGE_ERFOPEN; continue;
				}
			}
			count = file_size - file_progress;
			count = (count > BSIZE) ? BSIZE : count;
			
			if (oi->d_recv(buff,sizeof(char)*count)<0){
				stage = STAGE_ERROR; continue;
			}

			ntrans = write(fd,buff,sizeof(char)*count);
			if (ntrans != count*sizeof(char)){
				stage = STAGE_ERFWRITE; continue;
			}

			dack = 32;
			if (oi->d_send(&dack,sizeof(dack))<0){
				stage = STAGE_ERROR; continue;
			}
				
			file_progress += count;
			if (file_progress == file_size)
				stage = STAGE_FINISH;
		}
		
		
		else if (stage == STAGE_FINISH){
			stopped = true;
		}
		else{ /* error! */
			stopped = true;			
		}
	}
}

	if (fd>=0) close(fd);
	if (oi){
		oi->d_stop();
		oi->d_disconnect();
		delete oi;
	}

	free(buff);
	stopped = false;
}

Соседние файлы в папке net_copy