OSDN Git Service

Replaced \t with 4 spaces.
[greensite/jasmine.git] / network / tcpnetwork.cxx
1 #include "tcpnetwork.h"
2 #include <cstring>
3 #include "../structures/header.h"
4
5 using namespace network;
6 using namespace enc_hash;
7 using namespace structures;
8 using namespace std;
9
10 //Tpc server implementation
11 tcpServer::tcpServer(quint64 buffersize, QObject *parent):QTcpServer(parent){this->buffersize=buffersize;}
12
13 void tcpServer::incomingConnection(int handle){
14     tcpSocket *socket=new tcpSocket(this->buffersize,this);
15     if(!socket->setSocketDescriptor(handle)){
16         emit this->socket_error(*socket);
17         return;
18     }
19     if(emit this->pending(*socket)) this->newConnection();
20     else socket->abort();
21 }
22
23 //Tcp socket implementation
24 tcpSocket::tcpSocket(const quint64 buffersize, QObject *parent):QTcpSocket(parent){
25     this->buffer_size=buffersize;
26     this->canceled=false;
27     this->event=tcpSocket::headsize;
28     connect(this,SIGNAL(disconnected()),SLOT(deleteLater()));
29     connect(this,SIGNAL(readyRead()),SLOT(read_data()));
30 #ifdef DEBUG
31     qDebug()<<"TcpSocket is constructed.";
32     qDebug()<<"Status:";
33     qDebug()<<"Blocked:"<<this->signalsBlocked();
34 #endif
35 }
36 tcpSocket::tcpSocket(const QString &senderName,const quint64 buffersize,QObject *parent):QTcpSocket(parent){
37     this->buffer_size=buffersize;
38     this->senderName=senderName;
39 }
40
41 void tcpSocket::read_data(){
42     while(this->bytesAvailable()>0){
43 #ifdef DEBUG
44         qDebug()<<"Server Event Mode:"<<this->event<<"Server Available bytes:"<<this->bytesAvailable();
45 #endif
46         switch(this->event){
47         case tcpSocket::headsize:                this->size_event();            break;
48         case tcpSocket::header_receive:  this->header_event();          break;
49         case tcpSocket::msg:             this->msg_event();         break;
50         case tcpSocket::file:            this->file_event();        break;
51         }
52     }
53 }
54 void tcpSocket::size_event(){
55     if(this->bytesAvailable()<2) return;
56     char size_buf[2];
57     this->read(size_buf,sizeof(size_buf));
58     memcpy(&this->header_size,size_buf,
59            (sizeof(quint16)>sizeof(size_buf))?sizeof(quint16):sizeof(size_buf)
60            );
61     this->event=tcpSocket::header_receive;
62 }
63 void tcpSocket::header_event(){
64     if(this->bytesAvailable()<this->header_size) return;
65     else{
66         QByteArray data=this->read(this->header_size);
67         QDataStream datastream(data);
68         datastream>>this->head_data;
69         if(this->head_data==structures::header()){
70             this->setErrorString(tr("The header is empty."));
71             emit this->error(QAbstractSocket::UnknownSocketError);
72             this->disconnectFromHost();
73             return;
74         }
75         if(!this->head_data.fileName().isEmpty()){
76             this->where_to_save=(emit this->file_pending());
77             if(this->where_to_save.isEmpty()){
78                 this->write(QByteArray(1,0x00));
79
80                 this->setErrorString(tr("The filename is empty."));
81                 emit this->error(QAbstractSocket::UnknownSocketError);
82
83                 this->disconnectFromHost();
84                 return;
85             }
86         }
87     }
88     if(this->head_data.fileName().isEmpty()) this->event=tcpSocket::msg;
89     else this->event=tcpSocket::file;
90 }
91 void tcpSocket::msg_event(){
92     if((quint64)this->bytesAvailable()<this->header_data().datasize()) return;
93     quint64 final_readsize=this->head_data.datasize()%this->buffer_size,
94     read_count=(this->head_data.datasize()-final_readsize)/this->buffer_size;
95     QByteArray msg;
96     for(quint64 count=0;count<read_count;count++){
97         if(this->check_canceled_then_abort())return;
98         msg+=this->read(this->buffer_size);
99     }
100     if(this->check_canceled_then_abort())return;
101     msg+=this->read(final_readsize);
102
103     rmd6 generator;
104     if(this->head_data.ripemd160()==generator.compute_hash(msg))
105         emit this->msg_received(QString::fromUtf8(msg.data()));
106     else{
107         this->setErrorString(tr("The data has been broken."));
108         emit this->error(QAbstractSocket::UnknownSocketError);
109     }
110     this->disconnectFromHost();
111 }
112 void tcpSocket::file_event(){
113     if((quint64)this->bytesAvailable()<this->header_data().datasize()) return;
114     quint64 final_readsize=this->head_data.datasize()%this->buffer_size,
115     read_count=(this->head_data.datasize()-final_readsize)/this->buffer_size;
116     streamopen:
117     if(this->where_to_save.isEmpty()){
118         this->setErrorString(tr("The filename is empty."));
119         emit this->error(QAbstractSocket::UnknownSocketError);
120         this->disconnectFromHost();
121         return;
122     }
123     QFile file(this->where_to_save,this);
124     if(!file.open(QIODevice::Truncate|QIODevice::WriteOnly)){
125         this->where_to_save=emit this->fileStream_openFailed(file.error(),file.errorString());
126         goto streamopen;
127     }
128     for(quint64 count=0;count<read_count&&!this->check_canceled_then_abort();count++){
129         if(this->check_canceled_then_abort())return;
130         file.write(this->read(this->buffer_size));
131         emit this->file_receive_progress(file.pos());
132     }
133     if(this->check_canceled_then_abort())return;
134     file.write(this->read(final_readsize));
135     emit this->file_receive_progress(file.pos());
136     file.close();
137
138     rmd6 generator;
139     if(this->head_data.ripemd160()==generator.compute_hash(file))
140         emit this->file_saved();
141     else{
142         this->setErrorString(tr("The file has been broken."));
143         emit this->error(QAbstractSocket::UnknownSocketError);
144     }
145     this->disconnectFromHost();
146 }
147
148 bool tcpSocket::check_canceled_then_abort(){
149     if(this->canceled){
150         this->setErrorString(tr("The process has been canceled by user."));
151         emit this->error(QAbstractSocket::UnknownSocketError);
152         this->abort();
153         return true;
154     }
155     return false;
156 }
157 void tcpSocket::disconnectFromHostImplementation(){
158     this->canceled=true;
159     QTcpSocket::disconnectFromHost();
160 }
161 tcpSocket &tcpSocket::operator<<(const QString &msg){
162     if(this->state()!=QAbstractSocket::ConnectedState) return (*this);
163     this->head_data=header(this->senderName,msg);
164     QByteArray tmp_buffer;
165     QDataStream datastream(&tmp_buffer,QIODevice::WriteOnly);
166     datastream<<this->head_data;
167     quint16 size=(quint16)tmp_buffer.size();
168     this->write((char*)&size,sizeof(size)/sizeof(char));
169     if(!this->flush())return (*this);
170     this->write(tmp_buffer);
171     if(!this->flush())return (*this);
172     tmp_buffer.clear();
173     tmp_buffer=msg.toUtf8();
174     QBuffer memoryStream(&tmp_buffer,this);
175     if(!memoryStream.open(QIODevice::ReadOnly)){
176         this->setErrorString(tr("Memory Stream couldn't open."));
177         emit this->error(QAbstractSocket::UnknownSocketError);
178         return (*this);
179     }
180     while(this->write(memoryStream.read(this->buffer_size))>0)
181         if(!this->flush())return (*this);
182     memoryStream.close();
183
184     emit this->sentData();
185     return (*this);
186 }
187 tcpSocket &tcpSocket::operator<<(const QFileInfo &src_file){
188     QtLockedFile file(src_file.fileName());
189     if(!this->state()!=QAbstractSocket::ConnectedState)return (*this);
190     this->head_data=header(this->senderName,QFileInfo(file));
191     QByteArray tmp_buffer;
192     QDataStream datastream(tmp_buffer);
193     quint16 size=(quint16)tmp_buffer.size();
194     datastream<<this->head_data;
195     this->write((char*)&size,sizeof(size)/sizeof(char));
196     if(!this->flush())return (*this);
197     this->write(tmp_buffer);
198     if(!this->flush())return (*this);
199     tmp_buffer.clear();
200     emit this->file_header_sent();
201     if(!file.open(QIODevice::ReadOnly)){
202         this->setErrorString(tr("The file stream couldn't open."));
203         emit this->error(QAbstractSocket::UnknownSocketError);
204         return (*this);
205     }
206     file.lock(QtLockedFile::ReadLock);
207     while(this->write(file.read(this->buffer_size))>0&&!this->check_canceled_then_abort()){
208         if(!this->flush())return (*this);
209         emit this->sending_file_progress(file.pos());
210     }
211     file.unlock();
212     file.close();
213     emit this->sentData();
214     return (*this);
215 }
216 void tcpSocket::cancel(){this->canceled=true;}
217 QString tcpSocket::path_to_save() const{return this->where_to_save;}
218 header tcpSocket::header_data() const{return this->head_data;}