// Copyright (c) 2004 David Muse
// See the COPYING file for more information
#define EXCLUDE_RUDIMENTS_TEMPLATE_IMPLEMENTATIONS
#include <rudiments/modemclient.h>
#include <rudiments/chat.h>
#include <rudiments/device.h>
#include <rudiments/charstring.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#ifdef RUDIMENTS_NAMESPACE
namespace rudiments {
#endif
class modemclientprivate {
friend class modemclient;
private:
const char *_connectscript;
const char *_disconnectscript;
const char *_phonenumber;
};
modemclient::modemclient() : client(), modemutil() {
pvt=new modemclientprivate;
pvt->_connectscript="";
pvt->_disconnectscript="";
pvt->_phonenumber="";
type("modemclient");
}
modemclient::modemclient(const modemclient &m) : client(m), modemutil(m) {
pvt=new modemclientprivate;
modemclientClone(m);
type("modemclient");
}
modemclient &modemclient::operator=(const modemclient &m) {
if (this!=&m) {
client::operator=(m);
modemutil::operator=(m);
modemclientClone(m);
}
return *this;
}
void modemclient::modemclientClone(const modemclient &m) {
pvt->_connectscript=m.pvt->_connectscript;
pvt->_phonenumber=m.pvt->_phonenumber;
pvt->_disconnectscript=m.pvt->_disconnectscript;
}
modemclient::~modemclient() {
close();
delete pvt;
}
void modemclient::initialize(constnamevaluepairs *cd) {
if (cd) {
const char *devicename;
cd->getData("device",&devicename);
const char *baud;
cd->getData("baud",&baud);
const char *connectscript;
cd->getData("connectscript",&connectscript);
const char *phonenumber;
cd->getData("phonenumber",&phonenumber);
const char *disconnectscript;
cd->getData("disconnectscript",&disconnectscript);
const char *rwstr;
cd->getData("retrywait",&rwstr);
const char *rcstr;
cd->getData("retrycount",&rcstr);
initialize(devicename,baud,connectscript,phonenumber,
disconnectscript,
charstring::toInteger(rwstr),
charstring::toInteger(rcstr));
}
}
void modemclient::initialize(const char *devicename, const char *baud,
const char *connectscript,
const char *phonenumber,
const char *disconnectscript,
unsigned long retrywait,
unsigned long retrycount) {
modemutil::initialize(devicename,baud);
pvt->_connectscript=connectscript;
pvt->_phonenumber=phonenumber;
pvt->_disconnectscript=disconnectscript;
client::initialize("",-1,-1,retrywait,retrycount);
}
int modemclient::connect() {
constnamevaluepairs phnvp;
phnvp.setData("phonenumber",const_cast<char *>(pvt->_phonenumber));
unsigned long whichtry=0;
for (;;) {
delete[] *(_connecterror());
*(_connecterror())=NULL;
// open the serial port
// this is kind of lame, this class should somehow
// inherit from device
device modem;
if (!modem.open(_devicename(),O_RDWR|O_NOCTTY)) {
return RESULT_ERROR;
}
setFileDescriptor(modem.getFileDescriptor());
// set the file descriptor to -1 so it won't get
// closed when the instance of modem goes away
modem.setFileDescriptor(-1);
// configure the serial port
if (!configureSerialPort(fd(),_baud())) {
filedescriptor::close();
return RESULT_ERROR;
}
// run connectscript here...
chat ch(this);
int result=ch.runScript(pvt->_connectscript,
_connecterror(),&phnvp);
// runScript() will return RESULT_(SUCCESS|ABORT|TIMEOUT|ERROR)
// or a number >= 2 indicating that one of the abort conditions
// occurred. If we got an abort condition or timeout, retry.
if (result<=RESULT_SUCCESS && result!=RESULT_TIMEOUT) {
return result;
}
// handle retry
close();
whichtry++;
if (whichtry==_retrycount()) {
// return the last thing that caused us to retry
return result;
}
// even though the modem's file descriptor is closed here,
// we use waitForNonBlockingRead to pause between retrys,
// in case we're using a listener which could return an abort
int waitresult=waitForNonBlockingRead(_retrywait(),0);
if (waitresult==RESULT_ABORT || waitresult==RESULT_ERROR) {
return waitresult;
}
}
}
bool modemclient::close() {
if (fd()!=-1) {
chat ch(this);
ch.runScript(pvt->_disconnectscript,NULL);
return filedescriptor::close();
}
return true;
}
#ifdef RUDIMENTS_NAMESPACE
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1