00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef _WIN32
00024 #pragma warning(disable:4786)
00025 #endif
00026 #include <sys/types.h>
00027 #include <sys/stat.h>
00028 #ifndef _WIN32
00029 #include <unistd.h>
00030 #endif
00031
00032 #include <Utility.h>
00033 #include "BString.h"
00034 #include "Session.h"
00035 #include "PeerHandler.h"
00036 #include "MetainfoSocket.h"
00037 #include "Exception.h"
00038 #include "BTDictionary.h"
00039
00040 #ifdef _DEBUG
00041 #define DEB(x) x
00042 #else
00043 #define DEB(x)
00044 #endif
00045
00046
00047 int MetainfoSocket::m_nr = 0;
00048
00049
00050 MetainfoSocket::MetainfoSocket(ISocketHandler& h)
00051 :TcpSocket(h)
00052 ,m_filenr(++m_nr)
00053 ,m_fil(NULL)
00054 ,m_state(STATE_GET_LENGTH)
00055 ,m_sz(0)
00056 ,m_sz_read(0)
00057 {
00058 DEB(printf("MetaInfoSocket()\n");)
00059 }
00060
00061
00062 MetainfoSocket::MetainfoSocket(ISocketHandler& h,const std::string& filename)
00063 :TcpSocket(h)
00064 ,m_filenr(0)
00065 ,m_filename(filename)
00066 ,m_fil(NULL)
00067 ,m_state(STATE_GET_LENGTH)
00068 ,m_sz(0)
00069 ,m_sz_read(0)
00070 {
00071 DEB(printf("MetaInfoSocket()\n");)
00072 }
00073
00074
00075 MetainfoSocket::~MetainfoSocket()
00076 {
00077 DEB(printf("~MetaInfoSocket()\n");)
00078 if (m_fil)
00079 fclose(m_fil);
00080 }
00081
00082
00083 void MetainfoSocket::OnConnect()
00084 {
00085 DEB(printf("MetainfoSocket::OnConnect\n");)
00086 struct stat st;
00087 if (stat(m_filename.c_str(), &st) == -1)
00088 {
00089 perror("stat failed");
00090 SetCloseAndDelete();
00091 return;
00092 }
00093 SendBuf( (char *)&st.st_size, sizeof(off_t));
00094 FILE *fil = fopen(m_filename.c_str(), "rb");
00095 if (fil)
00096 {
00097 char buf[5000];
00098 int n = fread(buf,1,5000,fil);
00099 while (n > 0)
00100 {
00101 SendBuf(buf,n);
00102 n = fread(buf,1,5000,fil);
00103 }
00104 fclose(fil);
00105 }
00106 SetCloseAndDelete();
00107 }
00108
00109
00110 void MetainfoSocket::OnAccept()
00111 {
00112 DEB(printf("MetainfoSocket::OnAccept\n");)
00113 m_filename = "metafile." + Utility::l2string(m_filenr);
00114 m_fil = fopen(m_filename.c_str(), "wb");
00115 m_state = STATE_GET_LENGTH;
00116 }
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 void MetainfoSocket::OnRead()
00130 {
00131 TcpSocket::OnRead();
00132 while (ibuf.GetLength())
00133 {
00134 size_t l = ibuf.GetLength();
00135
00136 switch (m_state)
00137 {
00138 case STATE_GET_LENGTH:
00139 if (l < sizeof(off_t))
00140 return;
00141 ibuf.Read( (char *)&m_sz, sizeof(off_t));
00142 m_state = STATE_GET_FILE;
00143 DEB(printf("File length: %d bytes\n", m_sz);)
00144 break;
00145 case STATE_GET_FILE:
00146 {
00147 char slask[TCP_BUFSIZE_READ];
00148 ibuf.Read( slask, l);
00149 if (m_fil)
00150 fwrite(slask,1,l,m_fil);
00151 m_sz_read += l;
00152 }
00153 break;
00154 }
00155 }
00156 }
00157
00158
00159 void MetainfoSocket::OnDelete()
00160 {
00161 DEB(printf("MetainfoSocket::OnDelete\n");)
00162 if (m_fil)
00163 {
00164 fclose(m_fil);
00165 m_fil = NULL;
00166 if (m_sz_read == m_sz)
00167 {
00168 InitSession();
00169 }
00170 else
00171 {
00172 printf("Short metainfo file read - ignoring\n");
00173 }
00174 }
00175 }
00176
00177
00178 void MetainfoSocket::InitSession()
00179 {
00180 DEB(printf("InitSession\n");)
00181 try
00182 {
00183 FILE *fil = fopen(m_filename.c_str(), "rb");
00184 if (fil)
00185 {
00186 PeerHandler& ref = static_cast<PeerHandler&>(Handler());
00187 BString meta;
00188 meta.read_file(fil);
00189 fclose(fil);
00190 std::string info_hash = meta.GetHashAsString("info");
00191
00192 std::string copy_to = ref.GetTorrentDirectory() + "/" + info_hash + "/.metainfo";
00193 ref.mkpath(copy_to);
00194 fil = fopen(m_filename.c_str(), "rb");
00195 if (fil)
00196 {
00197 FILE *fil2 = fopen(copy_to.c_str(), "wb");
00198 char buf[1000];
00199 size_t n = fread(buf, 1, 1000, fil);
00200 while (n > 0)
00201 {
00202 fwrite(buf, 1, n, fil2);
00203 n = fread(buf, 1, 1000, fil);
00204 }
00205 fclose(fil2);
00206 fclose(fil);
00207 }
00208 if (ref.SessionExists(info_hash))
00209 {
00210 DEB(printf("Session for hash %s already exists\n", info_hash.c_str());)
00211 }
00212 else
00213 {
00214 DEB(printf("Hash: %s\n", info_hash.c_str());)
00215 Session *sess = new Session(Handler(), info_hash);
00216 ref.RegSession( sess );
00217 sess -> SetHash(meta.GetHash("info"));
00218 BTString *p;
00219 if ((p = meta.GetString("announce")) != NULL)
00220 {
00221 sess -> SetAnnounce(p -> GetValue());
00222 }
00223 std::string name;
00224 if ((p = meta.GetString("info.name")) != NULL)
00225 {
00226 sess -> SetName(name = p -> GetValue());
00227 }
00228 BTInteger *piecelength = meta.GetInteger("info.piece length");
00229 if (piecelength)
00230 {
00231 sess -> SetPieceLength(piecelength -> GetVal());
00232 }
00233 BTInteger *length = meta.GetInteger("info.length");
00234 if (length)
00235 {
00236 sess -> AddFile(length -> GetVal());
00237 }
00238 else
00239 {
00240 BTObject *p = meta.GetBTObject("info.files");
00241 BTList *files = dynamic_cast<BTList *>(p);
00242 if (files)
00243 {
00244 btobject_v& ref = files -> GetList();
00245 for (btobject_v::iterator it = ref.begin(); it != ref.end(); it++)
00246 {
00247 BTDictionary *p = dynamic_cast<BTDictionary *>(*it);
00248 if (p)
00249 {
00250 BTInteger *length = dynamic_cast<BTInteger *>(p -> Find("length"));
00251 BTList *path = dynamic_cast<BTList *>(p -> Find("path"));
00252 if (path && length)
00253 {
00254 btobject_v& ref = path -> GetList();
00255 std::string pathname = name;
00256 for (btobject_v::iterator it = ref.begin(); it != ref.end(); it++)
00257 {
00258 BTString *p = dynamic_cast<BTString *>(*it);
00259 if (p)
00260 pathname += "/" + p -> GetValue();
00261 }
00262 sess -> AddFile(pathname, length -> GetVal());
00263 }
00264 }
00265 }
00266 }
00267 }
00268
00269 BTString *pieces = meta.GetString("info.pieces");
00270 if (pieces)
00271 {
00272 sess -> SetPieces( pieces -> GetValue() );
00273 }
00274 sess -> CreateFileManager();
00275
00276 sess -> Load();
00277
00278
00279
00280
00281
00282
00283 }
00284
00285 unlink(m_filename.c_str());
00286 }
00287 }
00288 catch (const Exception& e)
00289 {
00290 Handler().LogError(this, "InitSession", 0, e.GetText(), LOG_LEVEL_ERROR);
00291 }
00292 }
00293
00294