]> code.citadel.org Git - citadel.git/commitdiff
foo
authorArt Cancro <ajc@citadel.org>
Tue, 11 May 1999 02:10:30 +0000 (02:10 +0000)
committerArt Cancro <ajc@citadel.org>
Tue, 11 May 1999 02:10:30 +0000 (02:10 +0000)
daphne/citclient-wxsocket.cpp [new file with mode: 0644]
daphne/citclient.cpp
daphne/includes.hpp

diff --git a/daphne/citclient-wxsocket.cpp b/daphne/citclient-wxsocket.cpp
new file mode 100644 (file)
index 0000000..4b6faab
--- /dev/null
@@ -0,0 +1,371 @@
+#include "includes.hpp"
+
+//  
+//     TRANSPORT LAYER OPERATIONS
+//
+
+
+
+// Attach to the Citadel server
+// FIX (add check for not allowed to log in)
+int CitClient::attach(wxString host, wxString port) {
+       wxString ServerReady;
+       wxIPV4address addr;
+
+        if (sock->IsConnected())
+        sock->Close();
+
+        addr.Hostname(host);
+        addr.Service(port);
+        sock->SetNotify(0);
+        sock->Connect(addr, TRUE);
+        if (sock->IsConnected()) {
+                cout << "Connect succeeded\n" ;
+                serv_gets(ServerReady);
+                initialize_session();
+               curr_host = host;       // Remember host and port, in case
+               curr_port = port;       // we need to auto-reconnect later
+                return(0);
+        } else {
+                cout << "Connect failed\n" ;
+                return(1);
+        }
+}
+
+
+// constructor
+CitClient::CitClient(void) {
+
+        wxSocketHandler::Master();
+        sock = new wxSocketClient();
+
+       // The WAITALL flag causes reads to block.  Don't use it.
+        //sock->SetFlags(wxSocketBase::WAITALL);
+        sock->SetFlags(wxSocketBase::NONE);
+
+        wxSocketHandler::Master().Register(sock);
+        sock->SetNotify(wxSocketBase::REQ_LOST);
+
+       (void)new keepalive(this);
+}
+
+
+// destructor
+CitClient::~CitClient(void) {
+       // Be nice and log out from the server if it's still connected
+       sock->Close();
+}
+
+
+
+void CitClient::detach(void) {
+        wxString buf;
+
+        if (sock->IsConnected()) {
+                serv_puts("QUIT");
+                serv_gets(buf);
+                sock->Close();
+        }
+}
+
+
+
+// Is this client connected?  Simply return the IsConnected status of sock.
+bool CitClient::IsConnected(void) {
+        return sock->IsConnected();
+}
+
+
+
+
+
+// Read a line of text from the server
+void CitClient::serv_gets(wxString& buf) {
+       static char charbuf[512];
+       static size_t nbytes = 0;
+       int i;
+       int nl_pos = (-1);
+
+
+       do {
+               sock->Read(&charbuf[nbytes], (sizeof(charbuf)-nbytes) );
+               nbytes += sock->LastCount();
+               for (i=nbytes; i>=0; --i)
+                       if (charbuf[i] == 10) nl_pos = i;
+       } while (nl_pos < 0);
+
+       charbuf[nbytes] = 0;
+       charbuf[nl_pos] = 0;
+
+       buf = charbuf;
+       strcpy(charbuf, &charbuf[nl_pos + 1]);
+       nbytes = nbytes - (nl_pos + 1);
+
+       cout << "> " << buf << "(len=" << nl_pos << ")\n";
+}
+
+
+
+
+
+
+// Write a line of text to the server
+void CitClient::serv_puts(wxString buf) {
+
+        cout << "< " << buf << "\n" ;
+        sock->Write((const char *)buf, buf.Len());
+        sock->Write("\n", 1);
+}
+
+
+
+
+
+
+
+
+
+//
+//             SESSION LAYER OPERATIONS
+//
+
+
+// Server transaction (returns first digit of server response code)
+int CitClient::serv_trans(
+                       wxString& command,
+                       wxString& response,
+                       wxString& xferbuf,
+                       wxString desired_room
+                       ) {
+
+        int first_digit, i, pos;
+       wxString buf, pw, junk;
+       bool express_messages_waiting = FALSE;
+
+       // If the caller specified that this transaction must take place
+       // in a particular room, make sure we're in that room.
+       if (desired_room.Length() > 0) {
+               if (desired_room.CmpNoCase(CurrentRoom) != 0) {
+                       pw = "";
+                       GotoRoom(desired_room, pw, junk);
+               }
+       }
+
+
+       // If a mutex is to be wrapped around this function in the future,
+       // it must begin HERE.
+       cout << "Beginning transaction\n";
+       wxBeginBusyCursor();
+       Critter.Enter();
+
+       serv_puts(command);
+       
+       if (IsConnected() == FALSE) {
+               wxSleep(5);     // Give a crashed server some time to restart
+               cout << "Reconnecting session\n";
+               reconnect_session();
+               serv_puts(command);
+       }
+
+       serv_gets(response);
+
+       first_digit = (response.GetChar(0)) - '0';
+
+       if (response.GetChar(3) == '*')
+               express_messages_waiting = TRUE;
+
+       if (first_digit == 1) {                 // LISTING_FOLLOWS
+               xferbuf.Empty();
+               while (serv_gets(buf), buf != "000") {
+                       xferbuf.Append(buf + "\n");
+               }
+       } else if (first_digit == 4) {          // SEND_LISTING
+               buf = xferbuf;
+               while (buf.Length() > 0) {
+                       pos = buf.Find('\n', FALSE);
+                       if ((pos < 0) && (buf.Length() < 250)) {
+                               serv_puts(buf + "\n");
+                               buf.Empty();
+                       } else if ((pos < 250) && (pos >= 0)) {
+                               serv_puts(buf.Left(pos+1));
+                               buf = buf.Mid(pos+1);
+                       } else {
+                               pos = buf.Left(250).Find(' ', TRUE);
+                               if ((pos < 250) && (pos >= 0)) {
+                                       serv_puts(buf.Left(pos) + "\n");
+                                       buf = buf.Mid(pos+1);
+                               } else {
+                                       serv_puts(buf.Left(250) + "\n");
+                                       buf = buf.Mid(pos);
+                               }
+                       }
+               }
+               serv_puts("000");
+       }
+
+       // If a mutex is to be wrapped around this function in the future,
+       // it must end HERE.
+       cout << "Ending transaction...\n";
+       Critter.Leave();
+       wxEndBusyCursor();
+       cout << "...done.\n";
+
+       if (express_messages_waiting) {
+               download_express_messages();
+       }
+
+       cout << "serv_trans() returning " << first_digit << "\n";
+       return first_digit;
+}
+
+// Shorter forms of serv_trans()
+int CitClient::serv_trans(
+                       wxString& command,
+                       wxString& response,
+                       wxString& xferbuf
+                       ) {
+       return serv_trans(command, response, xferbuf, "");
+}
+
+int CitClient::serv_trans(wxString& command, wxString& response) {
+       wxString junklist;
+       return serv_trans(command, response, junklist);
+}
+
+int CitClient::serv_trans(wxString& command) {
+       wxString junkbuf;
+       return serv_trans(command, junkbuf);
+}
+
+//
+//             PRESENTATION LAYER OPERATIONS
+//
+
+
+void CitClient::download_express_messages(void) {
+       wxString sendcmd, recvcmd, x_user, x_sys;
+       wxString xferbuf;
+
+       sendcmd = "GEXP";
+       while (serv_trans(sendcmd, recvcmd, xferbuf) == 1) {
+               extract(x_user, recvcmd, 3);
+               extract(x_sys, recvcmd, 4);
+               (void)new express_message(this, x_user, x_sys, xferbuf);
+       }
+}
+
+
+
+// Set up some things that we do at the beginning of every session
+void CitClient::initialize_session(void)  {
+       wxString info;
+       wxString sendcmd;
+       wxString recvcmd;
+       int i, pos;
+       wxString *infoptr;
+       wxString infoline;
+
+       CurrentRoom = "";
+
+       sendcmd = "IDEN 0|6|001|Daphne";
+       serv_trans(sendcmd);
+
+       sendcmd = "INFO";
+       if (serv_trans(sendcmd, recvcmd, info)==1) {
+               i = 0;
+               while (pos = info.Find('\n', FALSE),  (pos >= 0) ) {
+                       infoline = info.Left(pos);
+                       info = info.Mid(pos+1);
+                       switch(i) {
+
+                       case 0:         SessionID       = atoi(infoline);
+                       case 1:         NodeName        = infoline;
+                       case 2:         HumanNode       = infoline;
+                       case 3:         FQDN            = infoline;
+                       case 4:         ServerSoftware  = infoline;
+                       case 5:         ServerRev       = atoi(infoline);
+                       case 6:         GeoLocation     = infoline;
+                       case 7:         SysAdmin        = infoline;
+                       case 8:         ServerType      = atoi(infoline);
+                       case 9:         MorePrompt      = infoline;
+                       case 10:        UseFloors       = ((atoi(infoline)>0)
+                                                       ? TRUE : FALSE);
+                       case 11:        PagingLevel     = atoi(infoline);
+
+                       ++i;
+                       }
+               }
+       }
+}
+
+
+
+// Goto a room
+
+bool CitClient::GotoRoom(wxString roomname, wxString password,
+                       wxString& server_response) {
+       int retval;
+       wxString sendcmd, recvcmd;
+
+       sendcmd = "GOTO " + roomname + "|" + password;
+       retval = serv_trans(sendcmd, recvcmd);
+       server_response = recvcmd;
+
+       if (retval != 2) return FALSE;
+
+       extract(CurrentRoom, recvcmd.Mid(4), 0);
+       BigMDI->SetStatusText(CurrentRoom, 2);
+       return TRUE;
+}
+
+
+
+// Reconnect a broken session
+
+void CitClient::reconnect_session(void) {
+       wxString sendcmd;
+
+       CurrentRoom = "__ This is not the name of any valid room __";
+
+       if (attach(curr_host, curr_port) != 0) {
+               // FIX do this more elegantly
+               cout << "Could not re-establish session (1)\n";
+       }
+
+       sendcmd = "USER " + curr_user;
+       if (serv_trans(sendcmd) != 3) {
+               // FIX do this more elegantly
+               cout << "Could not re-establish session (2)\n";
+       }
+
+       sendcmd = "PASS " + curr_pass;
+       if (serv_trans(sendcmd) != 2) {
+               // FIX do this more elegantly
+               cout << "Could not re-establish session (3)\n";
+       }
+}
+
+
+
+
+
+
+// This is a simple timer that periodically wakes up and sends a NOOP to the
+// server.  This accomplishes two things: it keeps the server connection
+// alive by trickling some data through when it's otherwise idle, and it allows
+// the "check for express messages" loop to activate if it has to.
+
+keepalive::keepalive(CitClient *sock)
+       : wxTimer() {
+
+       which_sock = sock;              // Know which instance to refresh
+       Start(15000, FALSE);            // Call every 15 seconds
+}
+
+
+void keepalive::Notify(void) {
+       if (which_sock->IsConnected()) {
+               wxString noop = "NOOP";
+               which_sock->serv_trans(noop);
+       }
+}
index c9fbb7562f39e19f561ddb978c416ed4dc4e49c6..4b6faab8ca88af19bbfd194f4f39491e353e8c5d 100644 (file)
@@ -6,24 +6,6 @@
 
 
 
-/*
- * Define a new derived SocketClient
- */
-class MyClient: public wxSocketClient
-{
-public:
-       void OnNotify(wxRequestNotify WXUNUSED(flags)) {
-               cout << "Got An Event (tm)\n";
-       }
-};
-
-
-
-
-
-
-
-
 // Attach to the Citadel server
 // FIX (add check for not allowed to log in)
 int CitClient::attach(wxString host, wxString port) {
@@ -55,10 +37,11 @@ int CitClient::attach(wxString host, wxString port) {
 CitClient::CitClient(void) {
 
         wxSocketHandler::Master();
-        sock = new MyClient();
+        sock = new wxSocketClient();
 
        // The WAITALL flag causes reads to block.  Don't use it.
-        // sock->SetFlags(wxSocketBase::WAITALL);
+        //sock->SetFlags(wxSocketBase::WAITALL);
+        sock->SetFlags(wxSocketBase::NONE);
 
         wxSocketHandler::Master().Register(sock);
         sock->SetNotify(wxSocketBase::REQ_LOST);
@@ -103,6 +86,7 @@ void CitClient::serv_gets(wxString& buf) {
        int i;
        int nl_pos = (-1);
 
+
        do {
                sock->Read(&charbuf[nbytes], (sizeof(charbuf)-nbytes) );
                nbytes += sock->LastCount();
@@ -178,6 +162,7 @@ int CitClient::serv_trans(
        
        if (IsConnected() == FALSE) {
                wxSleep(5);     // Give a crashed server some time to restart
+               cout << "Reconnecting session\n";
                reconnect_session();
                serv_puts(command);
        }
index eb8bf9615669b6a08aef783d639d9ed6e4c87779..47b5f2b613ba6294990d18bb2c241c3c0692e91b 100644 (file)
@@ -36,7 +36,6 @@
 
 
 // CitClient represents an application-level connection to a Citadel server.
-class MyClient;
 class CitClient {
 public:
        CitClient(void);
@@ -87,7 +86,7 @@ public:
        wxString CurrentRoom;
 
 private:
-       MyClient *sock;                                 // transport layer
+       wxSocketClient *sock;                           // transport layer
        wxCriticalSection Critter;
        void serv_gets(wxString& buf);                  // session layer
        void serv_puts(wxString buf);                   // session layer