Bincimap 2.0.16
Easy Imapping
Loading...
Searching...
No Matches
imapserver.cc
Go to the documentation of this file.
1
8#include "broker.h"
9#include "globals.h"
10#include "imapparser.h"
11#include "imapserver.h"
12#include "iodevice.h"
13#include "iofactory.h"
14#include "session.h"
15
16using namespace ::Binc;
17using namespace ::std;
18
19namespace Binc {
20 void showGreeting(void);
21};
22
23IMAPServer::IMAPServer(int argc, char **argv)
24{
25 this->argc = argc;
26 this->argv = argv;
27 this->stubMode = false;
28 Session::getInstance().setState(Session::AUTHENTICATED);
29}
30
31IMAPServer::~IMAPServer(void)
32{
33}
34
35int IMAPServer::initialize(void)
36{
37 Session &session = Session::getInstance();
38 if (!session.initialize(argc, argv)) return 111;
39 return 0;
40}
41
42void IMAPServer::prepareForNextRequest(void)
43{
44 serverStatus = OK;
45
46 bincClient.setFlags(IODevice::HasInputLimit);
47 bincClient.flush();
48 bincClient.setMaxInputBufferSize(INPUT_BUFFER_LIMIT);
49
50 Session::getInstance().setLastError("");
51 Session::getInstance().clearResponseCode();
52}
53
54int IMAPServer::runStub(void)
55{
56 bincDebug << "IMAPServer::runStub(), running stub" << endl;
57 this->stubMode = true;
58 Session::getInstance().setState(Session::NONAUTHENTICATED);
59 return run();
60}
61
62int IMAPServer::run(void)
63{
64 Session &session = Session::getInstance();
65 bincLog.setOutputLevelLimit(IODevice::InfoLevel);
66 string pid = to_string(session.getPid());
67 std::string ip = session.getEnv("TCPREMOTEIP");
68 std::string userID = session.getEnv("AUTH_USER");
69
70 bincDebug << "IMAPServer::run(), started server" << endl;
71
72 if (this->stubMode) {
73 if (session.hasEnv("PROTOCOLDUMP"))
74 bincClient.enableProtocolDumping();
75 bincLog << "bincimap-up: pid " << pid
76 << " Connected: " << ip << "\n";
78 } else {
79 bincLog << "bincimapd: pid " << pid << " Session::" << session.getEnv("AUTH") << " <"
80 << userID << "> from: " << ip << "\n";
81 }
82 bincLog.flush();
83
84 do {
85 bincDebug << "IMAPServer::run(), preparing for next request" << endl;
86
87 prepareForNextRequest();
88
89 // Find the current state's broker.
90 BrokerFactory &brokerFactory = BrokerFactory::getInstance();
91 Broker *broker = brokerFactory.getBroker(session.getState());
92
93 bincDebug << "IMAPServer::run(), found broker " << (uintptr_t) broker
94 << " for state " << session.getState() << endl;
95
96 bool skipToNextRequest = false;
97
98 // Parse the stub of the IMAP request.
99 Request clientRequest;
100 int stubParseResult = broker->parseStub(clientRequest);
101 if (stubParseResult == Operator::TIMEOUT) {
102 serverStatus = Timeout;
103 break;
104 } else if (stubParseResult == Operator::REJECT) {
105 serverStatus = RequestRejected;
106 } else if (stubParseResult == Operator::ERROR) {
107 serverStatus = RequestError;
108 } else {
109 // Find an operator that recognizes the name of the request, and
110 // have it continue the parsing.
111 Operator *o = broker->get(clientRequest.getName());
112 if (!o) {
113 serverStatus = RequestRejected;
114 string err = "The command \"";
115 if (clientRequest.getUidMode()) err += "UID ";
116 err += clientRequest.getName();
117 err += "\" is unsupported in this state. ";
118 session.setLastError(err);
119 skipToNextRequest = true;
120 } else {
121 int parseResult = o->parse(clientRequest);
122 if (parseResult == Operator::TIMEOUT) {
123 serverStatus = Timeout;
124 } else if (parseResult == Operator::REJECT) {
125 serverStatus = RequestRejected;
126 } else if (parseResult == Operator::ERROR) {
127 serverStatus = RequestError;
128 } else {
129 session.addStatement();
130 Depot *dep = session.getDepot();
131
132 int processResult = o->process(*dep, clientRequest);
133 if (processResult == Operator::OK) {
134 } else if (processResult == Operator::NO) {
135 serverStatus = RequestRejected;
136 } else if (processResult == Operator::BAD) {
137 serverStatus = RequestError;
138 } else if (processResult == Operator::NOTHING) {
139 serverStatus = RequestIgnore; // answer given already
140 } else if (processResult == Operator::ABORT) {
141 session.setState(Session::LOGOUT);
142 }
143 }
144 }
145 }
146
147 // If a syntax error was detected, we skip all characters in the
148 // input stream up to and including '\n'.
149 if (serverStatus == RequestRejected) {
150 bincClient << clientRequest.getTag() << " NO "
151 << session.getResponseCode()
152 << clientRequest.getName() << " failed: "
153 << session.getLastError() << endl;
154 } else if (serverStatus == RequestError) {
155 bincClient << "* BAD "
156 << session.getLastError() << endl;
157 skipToNextRequest = true;
158 } else if (serverStatus == RequestIgnore) {
159 ;
160 } else if (serverStatus == OK && session.getState() != Session::LOGOUT) {
161 bincClient << clientRequest.getTag() << " OK";
162 if (clientRequest.getUidMode()) bincClient << " UID";
163 bincClient << " " << session.getResponseCode()
164 << clientRequest.getName() << " completed";
165 if (clientRequest.getContextInfo() != "")
166 bincClient << " (" << clientRequest.getContextInfo() << ")";
167
168 bincClient << endl;
169 } else {
170 // Timeout, ClientDisconnected
171 session.setState(Session::LOGOUT);
172 }
173
174 bincClient.flush();
175
176 if (skipToNextRequest) {
177 if (!bincClient.skipTo('\n')) {
178 if (bincClient.getLastError() == IODevice::Timeout) {
179 serverStatus = Timeout;
180 } else
181 serverStatus = ClientDisconnected;
182 break;
183 }
184 }
185 } while (session.getState() != Session::LOGOUT); // do line 81
186
187 // Session finished - write some log information
188
189 if (this->stubMode) {
190 bincLog << "bincimap-up: pid " << pid
191 << " (Read: " << session.getReadBytes()
192 << " Written: " << session.getWriteBytes() << ")\n";
193 } else {
194 bincLog << "bincimapd: pid " << pid
195 << " (Bodies: " << session.getBodies()
196 << " Statements: " << session.getStatements() << ")\n";
197 }
198
199 if (serverStatus == Timeout) {
200 bincClient << "* BYE Timeout after " << session.timeout()
201 << " seconds of inactivity\n";
202 bincClient.flush();
203 bincLog << "bincimapd: pid " << pid << " Timed out: <" << userID << "> after "
204 << IDLE_TIMEOUT << "s" << "\n";
205 } else if (serverStatus == ServerStatus::ClientDisconnected) {
206 bincLog << "bincimapd: pid " << pid << " Disconnected: " << ip << "\n";
207 } else {
208 if (this->stubMode) {
209 bincLog << "bincimap-up: pid " << pid << " Disconnected: " << ip << "\n";
210 } else {
211 bincLog << "bincimapd: pid " << pid << " Logged out: <" << userID << ">\n";
212 }
213 }
214 bincLog.flush();
215
216 return 0;
217}
Declaration of the Broker class.
Broker * getBroker(int state)
Definition: broker.cc:78
Operator * get(const std::string &name) const
Definition: broker.cc:106
Operator::ParseResult parseStub(Request &cmd)
Definition: broker.cc:114
virtual ParseResult parse(Request &) const =0
virtual ProcessResult process(Depot &, Request &)=0
const std::string & getTag(void) const
Definition: imapparser.cc:52
const std::string & getName(void) const
Definition: imapparser.cc:76
bool getUidMode(void) const
Definition: imapparser.cc:40
const std::string & getContextInfo(void) const
Definition: imapparser.cc:185
const int getState(void) const
Definition: session.cc:40
bool initialize(int argc, char *argv[])
void setLastError(const std::string &error) const
Definition: session.cc:185
void setState(int n)
Definition: session.cc:46
const std::string & getLastError(void) const
Definition: session.cc:179
int timeout() const
Definition: session.cc:218
Depot * getDepot(void) const
Definition: session.h:110
void addStatement(void)
Definition: session.cc:94
int getBodies(void) const
Definition: session.cc:112
int getWriteBytes(void) const
Definition: session.cc:124
int getReadBytes(void) const
Definition: session.cc:130
int getStatements(void) const
Definition: session.cc:118
pid_t getPid(void)
Definition: session.cc:209
const std::string & getResponseCode(void) const
Definition: session.cc:191
std::string getEnv(const std::string &key)
Definition: session.cc:230
bool hasEnv(const std::string &key) const
Definition: session.cc:224
Global constants.
Declaration of the common items for parsing IMAP input.
Declaration of the IMAPServer class.
Declaration of the IODevice class.
Declaration of the IOFactory class.
#define bincDebug
Definition: iofactory.h:46
#define bincLog
Definition: iofactory.h:50
#define bincClient
Definition: iofactory.h:31
Definition: bincimapd.cc:9
void showGreeting(void)
Definition: bincimapd.cc:10