00001 // ----------------------------------------------------------------------^ 00002 // Copyright (C) 2004, 2005, 2006, 2007, 2008 Giorgio Calderone 00003 // (mailto: <gcalderone@ifc.inaf.it>) 00004 // 00005 // This file is part of MCS. 00006 // 00007 // MCS is free software; you can redistribute it and/or modify 00008 // it under the terms of the GNU General Public License as published by 00009 // the Free Software Foundation; either version 2 of the License, or 00010 // (at your option) any later version. 00011 // 00012 // MCS is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 // GNU General Public License for more details. 00016 // 00017 // You should have received a copy of the GNU General Public License 00018 // along with MCS; if not, write to the Free Software 00019 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00020 // 00021 // ----------------------------------------------------------------------$ 00022 00023 #include "mcs.hh" 00024 using namespace mcs; 00025 00026 00027 00028 //-------------------------------------------------------- 00029 mcs::Client::Client(string path, string server, int port, 00030 bool synchro, bool SSL, 00031 unsigned int timeout) : 00032 Socket(server, port, timeout, timeout, SSL), 00033 RecordSet(), 00034 code(synchro), 00035 msg(synchro), 00036 out(synchro), 00037 recv(synchro), 00038 aux(synchro) 00039 { 00040 connected = false; 00041 init(0); 00042 lpath=path; 00043 if (lpath.empty()) 00044 lpath=Pwd(); 00045 00046 //Remove trailing slash 00047 remTrailing(lpath, "/"); 00048 00049 00050 connected = true; 00051 writetofile = true; 00052 lrecord = NULL; 00053 exec(""); //Read welcome message 00054 exec(MCS_CMD_CID); 00055 00056 unsigned int size; 00057 if (! File_Dir_Exist(lpath, size)) 00058 throw MCS_ERROR(MSG_DIRECTORY_NOT_FOUND, lpath.csz); 00059 00060 } 00061 00062 00063 mcs::Client::~Client() 00064 {} 00065 00066 00067 void mcs::Client::writeToFile(int des) 00068 { 00069 writetofile = true; 00070 fileDescriptor = des; 00071 } 00072 00073 00074 00075 00076 bool mcs::Client::login(string user, string pass, string db) 00077 { 00078 bool ret; 00079 string bl = " "; 00080 string cmd; 00081 00082 cmd = MCS_CMD_USERNAME + bl + user; 00083 ret = exec(cmd); 00084 if (ret) { 00085 cmd = MCS_CMD_PASSWORD + bl + pass; 00086 ret = exec(cmd); 00087 if (ret) { 00088 if (! db.empty()) { 00089 cmd = MCS_CMD_DBNAME + bl + db; 00090 ret = exec(cmd); 00091 } 00092 00093 if (ret) 00094 ret = exec(MCS_CMD_DBCONNECT); 00095 } 00096 } 00097 return ret; 00098 } 00099 00100 00101 void mcs::Client::clearRecords() 00102 { 00103 this->code.clear(); 00104 this->msg.clear(); 00105 this->out.clear(); 00106 this->recv.clear(); 00107 this->aux.clear(); 00108 } 00109 00110 00111 00112 bool sendRecord(Client* cli, Record* rec) 00113 { 00114 int i; 00115 00116 for (i=0; i<rec->count(); i++) 00117 if (! cli->exec(MCS_CMD_PUTDATA, &((*rec)[i]))) 00118 return false; 00119 00120 return true; 00121 } 00122 00123 00124 bool mcs::Client::exec(string cmd, Data* data) 00125 { 00126 string s="", msg, filename, fn; 00127 int i, code=0; 00128 unsigned int ui; 00129 bool ret=true; 00130 unsigned int size = 0; 00131 static string bl = " "; 00132 CommandParser hc; 00133 void* buf; 00134 Record* newRecordSet = NULL; 00135 static bool batch = false; 00136 Serializable* sss; 00137 00138 if (! connected) 00139 throw MCS_ERROR(MSG_NOT_CONNECTED); 00140 00141 if (! batch) { 00142 clearRecords(); 00143 if (lrecord) delete lrecord; 00144 lrecord = NULL; 00145 } 00146 00147 batch = true; 00148 00149 00150 if (! cmd.empty()) { 00151 hc.parseCmd(cmd); 00152 00153 if (hc.cmpCmd(MCS_CMD_PUT)) { 00154 filename = lpath + string("/") + hc.arg(0).sval(); 00155 if (! (size = File_Dir_Exist(filename, ui))) 00156 throw MCS_ERROR(MSG_CANT_OPEN_FILE, filename.csz); 00157 00158 cmd = MCS_CMD_PUT + bl + hc.arg(0).sval() + bl + itos(size); 00159 for (i=0; i<hc.optc(); i++) 00160 cmd += " -" + hc.opt(i); 00161 } 00162 00163 else if (hc.cmpCmd(MCS_CMD_PUTDATA)) { 00164 if (! data) 00165 throw MCS_ERROR(MSG_OBJECT_MISSING); 00166 00167 buf = data->getEntireBuffer(size); 00168 cmd = MCS_CMD_PUTDATA + bl + itos(size); 00169 for (i=0; i<hc.optc(); i++) 00170 cmd += " -" + hc.opt(i); 00171 } 00172 print(cmd); 00173 } 00174 00175 00176 s = getline(); 00177 while((s != string(MCS_PROMPT_OK)) && 00178 (s != string(MCS_PROMPT_WARN)) && 00179 (s != string(MCS_PROMPT_ERROR)) && 00180 (code != MSG_BYE)) { 00181 00182 if (s.csz[0] == *MCS_PRE) { 00183 code = extractCode(s.csz); 00184 msg = s.substr(4, 100000); 00185 00186 this->code.addField(code); 00187 this->msg.addField(msg); 00188 00189 if (code == MSG_BYE) { 00190 Socket::Close(); 00191 connected = false; 00192 event(MCS_CLIENT_DISCONNECT, Data((void*) NULL)); 00193 return true; 00194 } 00195 00196 //Search for auxiliary field in the answer.... 00197 vector<string> v = split(msg, MCS_SEP); 00198 00199 //...and put them in the recv vector 00200 for (ui=0; ui<v.size(); ui++) 00201 if ((ui % 2) == 1) //only items with an even index 00202 aux.addField(v[ui]); 00203 00204 00205 if (code >= 100) { 00206 ret=false; 00207 event(MCS_CLIENT_ERROR, Data(msg), code); 00208 } 00209 00210 00211 switch (code) { 00212 case MSG_SENDFILE_START: 00213 fn = aux.field(aux.count()-1).sval(); 00214 if (writetofile) 00215 recvData(fileDescriptor); 00216 else 00217 recvData(lpath + string ("/") + fn); 00218 00219 event(MCS_CLIENT_FILE, Data(fn)); 00220 break; 00221 00222 case MSG_SENDDATA_START: 00223 buf = NULL; 00224 size = recvData((char**) &buf, 0); 00225 i = aux.field(aux.count()-1).ival(); 00226 if (i == 1) { 00227 Data d(buf); 00228 this->recv.addField(d); 00229 event(MCS_CLIENT_DATA, d); 00230 } 00231 else { 00232 lrecord = new Record(buf); 00233 } 00234 00235 free(buf); 00236 break; 00237 00238 case MSG_RECVFILE_START: 00239 sss = new Serializable(filename, lchunksize); 00240 sendData(sss); 00241 delete sss; 00242 break; 00243 00244 case MSG_RECVDATA_START: 00245 sss = new Serializable(buf, size, true, lchunksize); 00246 sendData(sss); 00247 delete sss; 00248 //free(buf); //It has been freed by the Serializable object 00249 break; 00250 00251 case MSG_OUT: 00252 out.addField(s.substr(4, 100000)); 00253 break; 00254 00255 case MSG_NEW_RECORDSET: 00256 if (lrecord) { 00257 newRecordSet = new Record(*lrecord); 00258 delete lrecord; 00259 lrecord = NULL; 00260 } 00261 break; 00262 00263 00264 } 00265 } 00266 else 00267 throw MCS_ERROR(MSG_PROTOCOL, s.csz); 00268 00269 s = getline(); 00270 } 00271 00272 writetofile = false; 00273 if (newRecordSet) { 00274 Data d = newRecordSet->pop(); 00275 if (d.getTag() & MCS_RS_INSERT) 00276 d.setTag( d.getTag() - MCS_RS_INSERT); 00277 00278 init(d.getTag(), d.ival(), newRecordSet); 00279 delete newRecordSet; 00280 startFetch(); 00281 } 00282 00283 if (hc.cmpCmd(MCS_CMD_CID)) { 00284 lcid = aux[0].ival(); 00285 lchunksize = aux[1].ival(); 00286 } 00287 00288 00289 00290 batch = false; 00291 return ret; 00292 } 00293 00294 00295 00296 bool mcs::Client::fetch(unsigned int newpos, bool random) 00297 { 00298 static string bl = " "; 00299 if (! exec(MCS_CMD_RECORD + bl + itos(newpos))) { 00300 if (code[code.count()-1].ival() == MSG_ALREADY_AT_END_OF_FILE) 00301 return false; 00302 else 00303 throw MCS_ERROR( MSG_FETCH_ERROR, msg[0].sval()); 00304 } 00305 00306 00307 if (lrecord) { 00308 rec() = *lrecord; 00309 return true; 00310 } 00311 else 00312 return false; 00313 } 00314 00315 00316 00317 void mcs::Client::event(int op, Data d, int code) 00318 {} 00319 00320 00321 00322 bool mcs::Client::isConnected() 00323 { 00324 return connected; 00325 } 00326 00327 00328 00329 int mcs::Client::cid() { return lcid; } 00330 00331 00332 int mcs::Client::chunksize() { return lchunksize; } 00333 00334 00335 00336 00337 00338 00340 //mcs::ClientThread::ClientThread(string path, string server, 00341 // int port, bool SSL) : 00342 // Client(path, server, port, true, SSL) , Thread() 00343 //{ 00344 // start(); 00345 //} 00346 // 00347 // 00348 //mcs::ClientThread::~ClientThread() 00349 //{} 00350 // 00351 // 00352 //bool mcs::ClientThread::exec(string cmd, Data* d) 00353 //{ 00354 // bool ret = false; 00355 // enter(); 00356 // 00357 // try { 00358 // ret = Client::exec(cmd, d); 00359 // } 00360 // catch (Event e) { 00361 // leave(); 00362 // throw e; 00363 // } 00364 // 00365 // leave(); 00366 // return ret; 00367 //} 00368 // 00369 // 00370 //void mcs::ClientThread::run() 00371 //{ 00372 // for (;;) { 00373 // sleep_ms(500); 00374 // 00375 // if (tryenter()) { 00376 // try { 00377 // if (chkRecv(true, false)) 00378 // Client::exec(MCS_CMD_NOP); 00379 // } 00380 // catch (Event e) { 00381 // leave(); 00382 // cerr << e.where() << " " << e.msg() << endl; 00383 // exit(); 00384 // } 00385 // leave(); 00386 // } 00387 // } 00388 //} 00389 // 00390 //
![]() |
MCS (My Customizable Server) ver. 0.3.3-alpha3
|