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

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

.cpp
Скачиваний:
20
Добавлен:
17.04.2013
Размер:
7.02 Кб
Скачать
/*
  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;
}

void ThMain::stop()
{
	stopped = true;
}

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

	size_t count = 0, ntrans = 0;
	size_t BSIZE = 4096; /* 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){
	file_size = get_fsize(file.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 */
			sd = rem_socket(); /* open socket */
			if (sd < 0){ 
				stage = STAGE_ERSOCKET; continue;
			}

			/* CONNECT */
			if (rem_connect(sd, ip.ascii(), port) < 0){ 
				stage = STAGE_ERCONNECT; 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 (rem_send(sd, &file_size, sizeof(file_size)) < 0){
				stage = STAGE_ERSENDINFO; continue;
			}
			/* file name length */
			QTextCodec *codec = QTextCodec::codecForName("KOI8-R");
			QString tfile = codec->fromUnicode( file_name );
			len = tfile.length();
			if (rem_send(sd, &len, sizeof(len)) < 0){
				stage = STAGE_ERSENDINFO; continue;
			}
			/* file name */
			if (rem_send(sd, tfile.ascii(), len*sizeof(char)) < 0){
				stage = STAGE_ERSENDINFO; continue;
			}

			/* WAIT_ACK */
			/* after send information about file name and size
		 	 * we should wait for reply from remote machine */
			if (rem_recv(sd, &dack, sizeof(dack)) < 0){
				stage = STAGE_ERWAITACK; 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)){
				perror("read");
				stage = STAGE_ERFREAD; continue;
			}
			
			/* send block to remote machine */
			if (rem_send(sd, buff, sizeof(char)*count)<0){
				stage = STAGE_ERFSEND; continue;
			}

			/* wait for confirmation */
			if (rem_recv(sd, &dack, sizeof(dack))<0){
				stage = STAGE_ERWAITACK; 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 */
			sd = rem_socket(); /* open socket */
			if (sd < 0){
				stage = STAGE_ERSOCKET; continue;
			}

			/* accept connection */
			if (( sd = rem_accept(sd, port, &stopped)) < 0){ 
				stage = STAGE_ERACCEPT; continue;
			}

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

			if (rem_send(sd,&dack,sizeof(dack)) < 0){
				stage = STAGE_ERSENDACK; 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 (rem_recv(sd,buff,sizeof(char)*count)<0){
				stage = STAGE_ERFRECEIVE; continue;
			}

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

			dack = 32;
			if (rem_send(sd,&dack,sizeof(dack))<0){
				stage = STAGE_ERSENDACK; 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 (sd>=0) rem_disconnect(sd);

	free(buff);
	stopped = false;
}
Соседние файлы в папке net_copy