Client.cc

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 //

mcslogo

MCS (My Customizable Server) ver. 0.3.3-alpha3
Documentation generated on Thu Mar 22 13:22:23 UTC 2012