Добавил:
korayakov
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:
/*
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;
}