Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

SimpleTelnetClient.cxx

00001 /*
00002  * Copyright (C) 1991-9 Eric M. Hopper <hopper@omnifarious.mn.org>
00003  * 
00004  *     This program is free software; you can redistribute it and/or modify it
00005  *     under the terms of the GNU Lesser General Public License as published
00006  *     by the Free Software Foundation; either version 2 of the License, or
00007  *     (at your option) any later version.
00008  * 
00009  *     This program is distributed in the hope that it will be useful, but
00010  *     WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  *     Lesser General Public License for more details.
00013  * 
00014  *     You should have received a copy of the GNU Lesser General Public
00015  *     License along with this program; if not, write to the Free Software
00016  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  */
00018 
00019 /* $Header: /home/hopper/src/cvs/C++/StrMod/SimpleTelnetClient.cxx,v 1.5 2002/08/29 00:58:04 hopper Exp $ */
00020 
00021 // For a log, see ChangeLog
00022 
00023 #ifdef __GNUG__
00024 #  pragma implementation "SimpleTelnetClient.h"
00025 #endif
00026 
00027 #include "StrMod/SimpleTelnetClient.h"
00028 #include "StrMod/TelnetChunkerData.h"
00029 #include "StrMod/TelnetChars.h"
00030 
00031 namespace strmod {
00032 namespace strmod {
00033 
00034 using lcore::U1Byte;
00035 
00036 const STR_ClassIdent SimpleTelnetClient::identifier(43UL);
00037 const STR_ClassIdent SimpleTelnetClient::UPlug::identifier(44UL);
00038 const STR_ClassIdent SimpleTelnetClient::SPlug::identifier(45UL);
00039 
00040 SimpleTelnetClient::SimpleTelnetClient()
00041      : sent_do_supga_(false), sent_do_echo_(false),
00042        uplugcreated_(false), userplug_(*this),
00043        splugcreated_(false), serverplug_(*this)
00044 {
00045    reset();
00046 }
00047 
00048 SimpleTelnetClient::~SimpleTelnetClient()
00049 {
00050 }
00051 
00052 bool SimpleTelnetClient::deletePlug(Plug *plug)
00053 {
00054    if ((plug == &userplug_) && uplugcreated_)
00055    {
00056       uplugcreated_ = false;
00057       userplug_.unPlug();
00058       return(true);
00059    }
00060    else if ((plug == &serverplug_) && splugcreated_)
00061    {
00062       splugcreated_ = false;
00063       serverplug_.unPlug();
00064       return(true);
00065    }
00066    return(false);
00067 }
00068 
00069 void SimpleTelnetClient::reset()
00070 {
00071    sent_do_supga_ = false;
00072    sent_do_echo_ = false;
00073    if (doProtocol())
00074    {
00075       updatePlugFlags();
00076    }
00077 }
00078 
00079 StreamModule::Plug *SimpleTelnetClient::i_MakePlug(int side)
00080 {
00081    assert(((side == ToServer) && !splugcreated_) ||
00082           ((side == ToUser) && !uplugcreated_));
00083 
00084    if (side == ToServer)
00085    {
00086       splugcreated_ = true;
00087       return(&serverplug_);
00088    }
00089    else
00090    {
00091       uplugcreated_ = true;
00092       return(&userplug_);
00093    }
00094 }
00095 
00096 bool SimpleTelnetClient::doProtocol()
00097 {
00098    const U1Byte echoopt = 1;
00099    const U1Byte supgaopt = 3;
00100 
00101    if ((!sent_do_supga_ || !sent_do_echo_) && !toserver_)
00102    {
00103       U1Byte sendopt = echoopt;
00104       if (!sent_do_supga_)
00105       {
00106          sendopt = supgaopt;
00107          sent_do_supga_ = true;
00108       }
00109       else
00110       {
00111          sent_do_echo_ = true;
00112       }
00113 
00114       toserver_ = new TelnetChunker::OptionNegotiation(TelnetChars::O_DO, sendopt);
00115       return(true);
00116    }
00117    return(false);
00118 }
00119 
00120 void SimpleTelnetClient::updatePlugFlags()
00121 {
00122    setReadableFlagFor(&serverplug_,
00123                       (toserver_ || (uplugcreated_
00124                                      && userplug_.canReadOther())));
00125    setWriteableFlagFor(&userplug_,
00126                        (!toserver_ && splugcreated_
00127                         && serverplug_.canWriteOther()));
00128 
00129    setReadableFlagFor(&userplug_, touser_);
00130    setWriteableFlagFor(&serverplug_, (!touser_ && !toserver_));
00131 }
00132 
00133 const StrChunkPtr SimpleTelnetClient::userRead()
00134 {
00135    StrChunkPtr tmp = touser_;
00136    touser_.ReleasePtr();
00137    updatePlugFlags();
00138    return(tmp);
00139 }
00140 
00141 void SimpleTelnetClient::serverWrite(const StrChunkPtr &ptr)
00142 {
00143    assert(!toserver_);
00144    if (ptr->AreYouA(TelnetChunker::TelnetData::identifier))
00145    {
00146       if (ptr->AreYouA(TelnetChunker::OptionNegotiation::identifier))
00147       {
00148          StrChunkPtrT<TelnetChunker::OptionNegotiation> optneg =
00149             static_cast<TelnetChunker::OptionNegotiation *>(ptr.GetPtr());
00150 
00151          if (optneg->getRequest() == TelnetChars::O_WILL)
00152          {
00153             if ((optneg->getType() != 1) && (optneg->getType() != 3))
00154             {
00155                toserver_ = new TelnetChunker::OptionNegotiation(
00156                   TelnetChars::O_DONT, optneg->getType());
00157             }
00158          }
00159          else if (optneg->getRequest() == TelnetChars::O_DO)
00160          {
00161             if (optneg->getType() == 3)
00162             {
00163                toserver_ = new TelnetChunker::OptionNegotiation(
00164                   TelnetChars::O_WILL, 3);
00165             }
00166             else
00167             {
00168                toserver_ = new TelnetChunker::OptionNegotiation(
00169                   TelnetChars::O_WONT, optneg->getType());
00170             }
00171          }
00172          else if (optneg->getRequest() == TelnetChars::O_DONT)
00173          {
00174             toserver_ = new TelnetChunker::OptionNegotiation(
00175                TelnetChars::O_WONT, optneg->getType());
00176          }
00177          // WONTs are always ignored.  The rule about no automated retries of
00178          // failed negotiations prevents us from resending a DO if the server
00179          // refuses SUPRESS GOAHREAD or ECHO.  We'll just pretend it didn't
00180          // because it doesn't really matter in terms of how we process
00181          // things.
00182       }
00183       // Anything other than option negotiation is also ignored.
00184    }
00185    else
00186    {
00187       touser_ = ptr;
00188    }
00189    updatePlugFlags();
00190 }
00191 
00192 const StrChunkPtr SimpleTelnetClient::SPlug::i_Read()
00193 {
00194    SimpleTelnetClient &parent = getParent();
00195    if (parent.toserver_)
00196    {
00197       StrChunkPtr tmp = parent.toserver_;
00198       parent.toserver_.ReleasePtr();
00199       if (!parent.doProtocol())  // if doProtocol didn't put more in toserver_
00200       {
00201          parent.updatePlugFlags();
00202       }
00203       return(tmp);
00204    }
00205    else
00206    {
00207       assert(parent.uplugcreated_);
00208       UPlug &sibling = parent.userplug_;
00209 
00210       assert(sibling.pluggedInto());
00211       Plug &readfrom = *(sibling.pluggedInto());
00212 
00213       assert(readfrom.isReadable());
00214 
00215       setIsReading(readfrom, true);
00216       StrChunkPtr tmp = sibling.readOther();
00217       setIsReading(readfrom, false);
00218       return(tmp);
00219    }
00220 }
00221 
00222 void SimpleTelnetClient::UPlug::i_Write(const StrChunkPtr &ptr)
00223 {
00224    SimpleTelnetClient &parent = getParent();
00225    assert(!parent.toserver_ && parent.splugcreated_
00226           && parent.serverplug_.canWriteOther());
00227    assert(getFlagsFrom(*this).canwrite_);
00228 
00229    assert(parent.serverplug_.pluggedInto());
00230    Plug &writeto = *(parent.serverplug_.pluggedInto());
00231 
00232    if (getFlagsFrom(writeto).iswriting_)
00233    {
00234       parent.toserver_ = ptr;
00235       setWriteable(false);
00236    }
00237    else
00238    {
00239       setIsWriting(writeto, true);
00240       parent.serverplug_.writeOther(ptr);
00241       setIsWriting(writeto, false);
00242    }
00243 }
00244 
00245 };  // End namespace strmod
00246 };  // End namespace strmod

Generated on Wed Jan 29 00:32:44 2003 for libNet by doxygen1.3-rc1