bincimap

Log | Files | Refs | LICENSE

bincimapd.cc (5543B)


      1 /* -*- Mode: c++; -*- */
      2 /*  --------------------------------------------------------------------
      3  *  Filename:
      4  *    bincimapd.cc
      5  *  
      6  *  Description:
      7  *    Implementation of the main bincimapd service
      8  *
      9  *  Authors:
     10  *    Andreas Aardal Hanssen <andreas-binc curly bincimap spot org>
     11  *
     12  *  Bugs:
     13  *
     14  *  ChangeLog:
     15  *
     16  *  --------------------------------------------------------------------
     17  *  Copyright 2002-2005 Andreas Aardal Hanssen
     18  *
     19  *  This program is free software; you can redistribute it and/or modify
     20  *  it under the terms of the GNU General Public License as published by
     21  *  the Free Software Foundation; either version 2 of the License, or
     22  *  (at your option) any later version.
     23  *
     24  *  This program is distributed in the hope that it will be useful,
     25  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     26  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     27  *  GNU General Public License for more details.
     28  *
     29  *  You should have received a copy of the GNU General Public License
     30  *  along with this program; if not, write to the Free Software
     31  *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
     32  *  --------------------------------------------------------------------
     33  */
     34 #include <string>
     35 
     36 #include "broker.h"
     37 #include "depot.h"
     38 #include "recursivedescent.h"
     39 #include "io.h"
     40 #include "operators.h"
     41 #include "session.h"
     42 
     43 #include "maildirmessage.h"
     44 #include "maildir.h"
     45 
     46 using namespace ::std;
     47 using namespace Binc;
     48 
     49 //------------------------------------------------------------------------
     50 int main(int argc, char *argv[]) 
     51 {
     52   Session &session = Session::getInstance();
     53   if (!session.initialize(argc, argv))
     54     return 111;
     55 
     56   IO &com = IOFactory::getInstance().get(1);
     57   IO &logger = IOFactory::getInstance().get(2);
     58 
     59   logger << "<" << session.getUserID()
     60 	 << "> authenticated" << endl;
     61 
     62   logger.flushContent();
     63   bool recovery = false;
     64   bool timeout = false;
     65   bool disconnected = false;
     66   bool abrt = false;
     67 
     68   // Read requests and run functions
     69   do {
     70     com.enableInputLimit();
     71 
     72     // recover from syntax error. There will be trash in the input
     73     // buffer. We need to flush everything until we see an LF.
     74     if (recovery) {
     75       for (;;) {
     76 	int c = com.readChar();
     77 	if (c == '\n') break;
     78 	if (c == -1) {
     79 	  disconnected = true;
     80 	  abrt = true;
     81 	  break;
     82 	}
     83 
     84 	if (c == -2) {
     85 	  timeout = true;
     86 	  abrt = true;
     87 	  break;
     88 	}
     89       }
     90       
     91       if (abrt)
     92 	break;
     93     }
     94 
     95     Request request;
     96     session.setLastError("");
     97     session.clearResponseCode();
     98     recovery = false;
     99 
    100     BrokerFactory &brokerFactory = BrokerFactory::getInstance();
    101     Broker *broker = brokerFactory.getBroker(session.getState());
    102     if (!broker) {
    103       // will never happen
    104     }    
    105 
    106     com.noFlushOnEndl();
    107     com.flushContent();
    108     com.enableInputLimit();
    109 
    110     switch (broker->parseStub(request)) {
    111     case Operator::TIMEOUT:
    112       com << "* BYE Timeout after " << session.timeout()
    113 	  << " seconds of inactivity." << endl;
    114       timeout = true;
    115       abrt = true;
    116       break;
    117     case Operator::REJECT:
    118       com << "* NO " << session.getLastError() << endl;
    119       recovery = true;
    120       continue;
    121     case Operator::ERROR:
    122       com << "* BAD " << session.getLastError() << endl;
    123       recovery = true;
    124       continue;
    125     default:
    126       break;
    127     }
    128 
    129     if (abrt)
    130       break;
    131     
    132     Operator *o = broker->get(request.getName());
    133     if (!o) {
    134       com << request.getTag() << " NO The command \"" 
    135 	  << (request.getUidMode() ? "UID " : "")
    136 	  << request.getName()
    137 	  << "\" is unsupported in this state. " << endl;
    138       recovery = true;
    139       continue;
    140     }
    141 
    142     switch (o->parse(request)) {
    143     case Operator::TIMEOUT:
    144       com << "* BYE Timeout after " << session.timeout()
    145 	  << " seconds of inactivity." << endl;
    146       timeout = true;
    147       abrt = true;
    148       break;
    149     case Operator::REJECT:
    150       com << "* NO " << session.getLastError() << endl;
    151       recovery = true;
    152       continue;
    153     case Operator::ERROR:
    154       com << "* BAD " << session.getLastError() << endl;
    155       recovery = true;
    156       continue;
    157     default:
    158       break;
    159     }
    160 
    161     session.addStatement();
    162     Depot *dep = session.getDepot();
    163 
    164     switch (o->process(*dep, request)) {
    165     case Operator::OK:
    166       com << request.getTag() << " OK " << session.getResponseCode()
    167 	  << request.getName() << " completed" << endl;
    168       break;
    169     case Operator::NO: 
    170       com << request.getTag() << " NO " << session.getResponseCode()
    171           << request.getName() << " failed: " << session.getLastError() << endl;
    172       session.clearResponseCode();
    173       break;
    174     case Operator::BAD:
    175       com << request.getTag() << " BAD " << session.getResponseCode()
    176 	  << request.getName() << " failed: " << session.getLastError() 
    177 	  << endl;
    178       break;
    179     case Operator::NOTHING:
    180       break;
    181     case Operator::ABORT:
    182       session.setState(Session::LOGOUT);
    183       abrt = true;
    184       break;
    185     }
    186 
    187     if (abrt)
    188       break;
    189 
    190   } while (session.getState() != Session::LOGOUT);
    191 
    192   if (abrt) {
    193     logger << "shutting down (";
    194     if (timeout)
    195       logger << "timeout after " << session.idletimeout << "s";
    196     else
    197       logger << "client disconnected";
    198     logger << ") - bodies:" 
    199 	   << session.getBodies() << " statements:"
    200 	   << session.getStatements() << endl;
    201   } else {
    202     logger << "<" << session.getUserID() << "> logged off - bodies:" 
    203 	   << session.getBodies() << " statements:"
    204 	   << session.getStatements() << endl;
    205   }
    206 
    207   com.flushContent();
    208 
    209   return timeout ? 113 : 0;
    210 }