+
#include "includes.hpp"
+#include <unistd.h>
+
+
//
// 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();
+
+ if (sock.is_connected())
+ sock.detach();
+ if (sock.attach(host, port)==0) {
+ 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);
- }
+
+ return(0);
+ }
+ else 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();
+ sock.detach();
}
-
-
void CitClient::detach(void) {
- wxString buf;
+ wxString buf;
- if (sock->IsConnected()) {
- serv_puts("QUIT");
- serv_gets(buf);
- sock->Close();
- }
+ if (sock.is_connected()) {
+ serv_puts("QUIT");
+ serv_gets(buf);
+ sock.detach();
+ }
}
-
// Is this client connected? Simply return the IsConnected status of sock.
bool CitClient::IsConnected(void) {
- return sock->IsConnected();
+ return sock.is_connected();
}
-
-
// 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;
-
+ char charbuf[256];
+
+ sock.serv_gets(charbuf);
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);
+ sock.serv_puts(buf);
}
-
-
-
-
-
-
-
//
// SESSION LAYER OPERATIONS
//
// 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);
}
// 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;
}
CurrentRoom = "__ This is not the name of any valid room __";
+ // Give a crashed server some time to restart
+ sleep(5);
+
if (attach(curr_host, curr_port) != 0) {
// FIX do this more elegantly
cout << "Could not re-establish session (1)\n";
-#include <wx/wx.h> // General-purpose wxWin header
+#include <wx/wx.h>
#include <wx/listctrl.h>
-#include <wx/socket.h> // TCP socket client
+#include <wx/socket.h>
#include <wx/log.h>
#include <wx/imaglist.h>
#include <wx/treectrl.h>
#include <wx/toolbar.h>
-#include <wx/tokenzr.h> // For the string tokenizer
-#include <wx/thread.h> // No threads, but we need wxCriticalSection
-#include <wxhtml/wxhtml.h> // Vaclav Slavik's HTML display widget
+#include <wx/tokenzr.h>
+#include <wxhtml/wxhtml.h>
#define MAXFLOORS 128
#define DEFAULT_HOST "uncnsrd.mt-kisco.ny.us"
// Room flags (from ipcdef.h in the main Citadel distribution)
-
+//
#define QR_PERMANENT 1 /* Room does not purge */
#define QR_INUSE 2 /* Set if in use, clear if avail */
#define QR_PRIVATE 4 /* Set for any type of private room */
+// TCPsocket represents a socket-level TCP connection to a server.
+class TCPsocket {
+public:
+ TCPsocket::TCPsocket(void);
+ int attach(const char *, const char *);
+ void detach(void);
+ void serv_read(char *, int);
+ void serv_write(char *, int);
+ void serv_gets(char *);
+ void serv_puts(const char *);
+ bool is_connected(void);
+private:
+ int serv_sock;
+ int connectsock(const char *, const char *, const char *);
+ static void timeout(int);
+};
+
+
+
// CitClient represents an application-level connection to a Citadel server.
class CitClient {
+ friend TCPsocket::timeout(int);
public:
CitClient(void);
~CitClient(void);
wxString CurrentRoom;
private:
- wxSocketClient *sock; // transport layer
- wxCriticalSection Critter;
+ TCPsocket sock; // transport layer
void serv_gets(wxString& buf); // session layer
void serv_puts(wxString buf); // session layer
void reconnect_session(void); // session layer
void download_express_messages(void); // presentation layer
void initialize_session(void); // presentation layer
+
wxString curr_host;
wxString curr_port;
+
};