void SMTP::react( Event e ) { switch ( e ) { case Read: setTimeoutAfter( 1800 ); parse(); break; case Timeout: log( "Idle timeout" ); enqueue( "421 Tempus fugit\r\n" ); Connection::setState( Closing ); break; case Connect: case Error: case Close: break; case Shutdown: enqueue( "421 Server shutdown\r\n" ); break; } execute(); }
POP::POP( int s ) : SaslConnection( s, Connection::Pop3Server ), d( new PopData ) { d->challenge = randomChallenge(); ok( "Archiveopteryx POP3 server ready " + d->challenge ); setTimeoutAfter( 600 ); EventLoop::global()->addConnection( this ); }
void Connection::substitute( Connection * other, Event event ) { EventLoop::global()->removeConnection( this ); setTimeoutAfter( 10 ); d->type = other->d->type; d->l = other->d->l; other->d = d; other->d->pending = true; other->d->event = event; EventLoop::global()->addConnection( other ); }
void connect() { log( "Trying " + target.string(), Log::Debug ); if ( Connection::connect( target ) < 0 ) { next( true ); return; } setTimeoutAfter( 1 ); EventLoop::global()->addConnection( this ); }
IMAP::IMAP( int s ) : SaslConnection( s, Connection::ImapServer ), d( new IMAPData ) { if ( s < 0 ) return; EString banner = "* OK [CAPABILITY " + Capability::capabilities( this ) + "] " + Configuration::hostname() + " Archiveopteryx IMAP Server"; if ( !Configuration::toggle( Configuration::Security ) ) banner.append( " (security checking disabled)" ); banner.append( "\r\n" ); enqueue( banner ); setTimeoutAfter( 120 ); EventLoop::global()->addConnection( this ); }
void IMAP::setUser( User * user, const EString & mechanism ) { log( "Authenticated as " + user->login().ascii() + " using " + mechanism, Log::Significant ); SaslConnection::setUser( user, mechanism ); setState( Authenticated ); bool possiblyOutlook = true; List< Command >::Iterator i( d->commands ); while ( i && possiblyOutlook ) { EString tag = i->tag(); ++i; if ( tag.length() != 4 || tag.contains( '.' ) ) possiblyOutlook = false; } if ( possiblyOutlook ) setClientBug( Nat ); setTimeoutAfter( 1860 ); }
SMTP::SMTP( int s, Dialect dialect ) : SaslConnection( s, Connection::SmtpServer ), d( new SMTPData ) { Scope x( log() ); d->dialect = dialect; switch( dialect ) { case Smtp: enqueue( "220 ESMTP " ); break; case Lmtp: enqueue( "220 LMTP " ); break; case Submit: enqueue( "220 SMTP Submission " ); break; } enqueue( Configuration::hostname() ); enqueue( "\r\n" ); setTimeoutAfter( 1800 ); EventLoop::global()->addConnection( this ); }
void react( Event e ) { // If we've succeeded in making a connection, we can kill all of // the other connectors and substitute ourselves for the parent // connection. if ( e == Connect ) { List<SerialConnector>::Iterator it( connectors ); while ( it ) { SerialConnector * sc = it; if ( sc != this ) { EventLoop::global()->removeConnection( sc ); sc->close(); } ++it; } substitute( host, Connect ); host->setState( Connecting ); } // If there's an Error, we know we won't be able to connect, so // we remove ourselves from the List of connectors and connect() // the next one in line. If the initial 1-second timeout expires // we extend the timeout and yield without removing ourselves, // since the connection attempt may yet succeed. else if ( e == Error || e == Timeout ) { if ( e == Timeout ) { setTimeoutAfter( 10 ); timeouts++; } next( e == Error || timeouts > 1 ); } else { // XXX: If the EventLoop starts forwarding Read etc. to us, // we're deeply screwed. } }
void POP::react( Event e ) { switch ( e ) { case Read: setTimeoutAfter( 600 ); parse(); break; case Timeout: // We may not send any response. log( "Idle timeout" ); Connection::setState( Closing ); break; case Connect: break; case Error: Connection::setState( Closing ); break; case Close: break; case Shutdown: // RFC 1939 says that if the server times out, it should close // silently. It doesn't talk about server shutdown, so it // sounds sensible to do nothing in that case as well. break; } if ( d->state == Update ) Connection::setState( Closing ); if ( Connection::state() == Closing && session() ) session()->end(); }
void IMAP::react( Event e ) { d->bytesArrived += readBuffer()->size(); switch ( e ) { case Read: parse(); if ( d->bytesArrived > 32768 && state() == NotAuthenticated ) { log( ">32k received before login" ); enqueue( "* BYE overlong login sequence\r\n" ); Connection::setState( Closing ); if ( d->reader ) { Scope s( d->reader->log() ); d->reader->read(); } } break; case Timeout: if ( state() != Logout ) { log( "Idle timeout" ); enqueue( "* BYE Tempus fugit\r\n" ); } Connection::setState( Closing ); if ( d->reader ) { Scope s( d->reader->log() ); d->reader->read(); } setSession( 0 ); break; case Connect: break; case Error: case Close: if ( session() ) { log( "Unexpected close by client" ); setSession( 0 ); } if ( !d->commands.isEmpty() ) { List<Command>::Iterator i( d->commands ); while ( i ) { Command * c = i; ++i; if ( c->state() == Command::Unparsed || c->state() == Command::Blocked || c->state() == Command::Executing ) c->error( Command::No, "Unexpected close by client" ); } } break; case Shutdown: enqueue( "* BYE server shutdown\r\n" ); if ( session() && d->commands.isEmpty() ) setSession( 0 ); break; } runCommands(); d->bytesArrived -= readBuffer()->size(); if ( timeout() == 0 || ( e == Read && state() != NotAuthenticated ) ) { switch ( state() ) { case NotAuthenticated: setTimeoutAfter( 120 ); break; case Authenticated: case Selected: if ( idle() ) setTimeoutAfter( 3600 ); // one hour while IDLE else setTimeoutAfter( 1860 ); // a half-hour without break; case Logout: break; } } }