Line 1... |
Line 1... |
// $Id: Rw11VirtTermTcp.cpp 504 2013-04-13 15:37:24Z mueller $
|
// $Id: Rw11VirtTermTcp.cpp 508 2013-04-20 18:43:28Z mueller $
|
//
|
//
|
// Copyright 2013- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
// Copyright 2013- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
//
|
//
|
// This program is free software; you may redistribute and/or modify it under
|
// This program is free software; you may redistribute and/or modify it under
|
// the terms of the GNU General Public License as published by the Free
|
// the terms of the GNU General Public License as published by the Free
|
Line 11... |
Line 11... |
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
// for complete details.
|
// for complete details.
|
//
|
//
|
// Revision History:
|
// Revision History:
|
// Date Rev Version Comment
|
// Date Rev Version Comment
|
|
// 2013-04-20 508 1.0.1 add fSndPreConQue handling
|
// 2013-03-06 495 1.0 Initial version
|
// 2013-03-06 495 1.0 Initial version
|
// 2013-02-13 488 0.1 First draft
|
// 2013-02-13 488 0.1 First draft
|
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
|
|
/*!
|
/*!
|
\file
|
\file
|
\version $Id: Rw11VirtTermTcp.cpp 504 2013-04-13 15:37:24Z mueller $
|
\version $Id: Rw11VirtTermTcp.cpp 508 2013-04-20 18:43:28Z mueller $
|
\brief Implemenation of Rw11VirtTermTcp.
|
\brief Implemenation of Rw11VirtTermTcp.
|
*/
|
*/
|
|
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <sys/types.h>
|
#include <sys/types.h>
|
Line 68... |
Line 69... |
const uint8_t Rw11VirtTermTcp::kOpt_ECHO;
|
const uint8_t Rw11VirtTermTcp::kOpt_ECHO;
|
const uint8_t Rw11VirtTermTcp::kOpt_SGA;
|
const uint8_t Rw11VirtTermTcp::kOpt_SGA;
|
const uint8_t Rw11VirtTermTcp::kOpt_TTYP;
|
const uint8_t Rw11VirtTermTcp::kOpt_TTYP;
|
const uint8_t Rw11VirtTermTcp::kOpt_LINE;
|
const uint8_t Rw11VirtTermTcp::kOpt_LINE;
|
|
|
|
const size_t Rw11VirtTermTcp::kPreConQue_limit;
|
|
|
//------------------------------------------+-----------------------------------
|
//------------------------------------------+-----------------------------------
|
//! Default constructor
|
//! Default constructor
|
|
|
Rw11VirtTermTcp::Rw11VirtTermTcp(Rw11Unit* punit)
|
Rw11VirtTermTcp::Rw11VirtTermTcp(Rw11Unit* punit)
|
: Rw11VirtTerm(punit),
|
: Rw11VirtTerm(punit),
|
fFdListen(-1),
|
fFdListen(-1),
|
fFd(-1),
|
fFd(-1),
|
fState(ts_Closed),
|
fState(ts_Closed),
|
fTcpTrace(false)
|
fTcpTrace(false),
|
|
fSndPreConQue()
|
{
|
{
|
|
fStats.Define(kStatNVTPreConSave , "NVTPreConSave" ,
|
|
"VT snd bytes saved prior connect");
|
|
fStats.Define(kStatNVTPreConDrop , "NVTPreConDrop" ,
|
|
"VT snd bytes dropped prior connect");
|
fStats.Define(kStatNVTListenPoll , "NVTListenPoll" ,
|
fStats.Define(kStatNVTListenPoll , "NVTListenPoll" ,
|
"ListenPollHandler() calls");
|
"VT ListenPollHandler() calls");
|
fStats.Define(kStatNVTAccept, "NVTAccept", "socket accepts");
|
fStats.Define(kStatNVTAccept, "NVTAccept", "VT socket accepts");
|
fStats.Define(kStatNVTRcvRaw, "NVTRcvRaw", "raw bytes received");
|
fStats.Define(kStatNVTRcvRaw, "NVTRcvRaw", "VT raw bytes received");
|
fStats.Define(kStatNVTSndRaw, "NVTSndRaw", "raw bytes send");
|
fStats.Define(kStatNVTSndRaw, "NVTSndRaw", "VT raw bytes send");
|
}
|
}
|
|
|
//------------------------------------------+-----------------------------------
|
//------------------------------------------+-----------------------------------
|
//! Destructor
|
//! Destructor
|
|
|
Line 94... |
Line 102... |
{
|
{
|
if (fFdListen > 2) {
|
if (fFdListen > 2) {
|
Server().RemovePollHandler(fFdListen);
|
Server().RemovePollHandler(fFdListen);
|
close(fFdListen);
|
close(fFdListen);
|
}
|
}
|
if (fFd > 2) {
|
if (Connected()) {
|
Server().RemovePollHandler(fFd);
|
Server().RemovePollHandler(fFd);
|
close(fFd);
|
close(fFd);
|
}
|
}
|
}
|
}
|
|
|
Line 180... |
Line 188... |
bool Rw11VirtTermTcp::Snd(const uint8_t* data, size_t count, RerrMsg& emsg)
|
bool Rw11VirtTermTcp::Snd(const uint8_t* data, size_t count, RerrMsg& emsg)
|
{
|
{
|
fStats.Inc(kStatNVTSnd);
|
fStats.Inc(kStatNVTSnd);
|
const uint8_t* pdata = data;
|
const uint8_t* pdata = data;
|
const uint8_t* pdataend = data+count;
|
const uint8_t* pdataend = data+count;
|
|
if (count == 0) return true; // quit if nothing to do
|
|
|
|
if (!Connected()) { // if not connected keep last chars
|
|
for (size_t i=0; i<count; i++) fSndPreConQue.push_back(data[i]);
|
|
fStats.Inc(kStatNVTPreConSave, double(count));
|
|
while (fSndPreConQue.size() > kPreConQue_limit) {
|
|
fSndPreConQue.pop_front();
|
|
fStats.Inc(kStatNVTPreConDrop);
|
|
}
|
|
return true;
|
|
}
|
|
|
uint8_t obuf[1024];
|
uint8_t obuf[1024];
|
while (pdata < pdataend) {
|
while (pdata < pdataend) {
|
uint8_t* pobuf = obuf;
|
uint8_t* pobuf = obuf;
|
uint8_t* pobufend = obuf+1024;
|
uint8_t* pobufend = obuf+1024;
|
Line 229... |
Line 248... |
case ts_Subiac: t_state = "ts_Subiac"; break;
|
case ts_Subiac: t_state = "ts_Subiac"; break;
|
default: t_state = "???";
|
default: t_state = "???";
|
}
|
}
|
os << bl << " fState: " << t_state << endl;
|
os << bl << " fState: " << t_state << endl;
|
os << bl << " fTcpTrace: " << fTcpTrace << endl;
|
os << bl << " fTcpTrace: " << fTcpTrace << endl;
|
|
os << bl << " fSndPreConQue.size" << fSndPreConQue.size() << endl;
|
Rw11VirtTerm::Dump(os, ind, " ^");
|
Rw11VirtTerm::Dump(os, ind, " ^");
|
return;
|
return;
|
}
|
}
|
|
|
//------------------------------------------+-----------------------------------
|
//------------------------------------------+-----------------------------------
|
Line 263... |
Line 283... |
uint8_t buf_4[3] = {kCode_IAC, kCode_WILL, kOpt_BIN};
|
uint8_t buf_4[3] = {kCode_IAC, kCode_WILL, kOpt_BIN};
|
uint8_t buf_5[3] = {kCode_IAC, kCode_DO , kOpt_BIN};
|
uint8_t buf_5[3] = {kCode_IAC, kCode_DO , kOpt_BIN};
|
|
|
int nerr = 0;
|
int nerr = 0;
|
|
|
|
// send initial negotiation WILLs and DOs
|
if (write(fFd, buf_1, sizeof(buf_1)) < 0) nerr += 1;
|
if (write(fFd, buf_1, sizeof(buf_1)) < 0) nerr += 1;
|
if (write(fFd, buf_2, sizeof(buf_2)) < 0) nerr += 1;
|
if (write(fFd, buf_2, sizeof(buf_2)) < 0) nerr += 1;
|
if (write(fFd, buf_3, sizeof(buf_3)) < 0) nerr += 1;
|
if (write(fFd, buf_3, sizeof(buf_3)) < 0) nerr += 1;
|
if (write(fFd, buf_4, sizeof(buf_4)) < 0) nerr += 1;
|
if (write(fFd, buf_4, sizeof(buf_4)) < 0) nerr += 1;
|
if (write(fFd, buf_5, sizeof(buf_5)) < 0) nerr += 1;
|
if (write(fFd, buf_5, sizeof(buf_5)) < 0) nerr += 1;
|
|
|
|
// send connect message
|
if (nerr==0) {
|
if (nerr==0) {
|
stringstream msg;
|
stringstream msg;
|
msg << "\r\nconnect on port " << fChannelId
|
msg << "\r\nconnect on port " << fChannelId
|
<< " for " << Unit().Name() << "\r\n\r\n";
|
<< " for " << Unit().Name() << "\r\n\r\n";
|
string str = msg.str();
|
string str = msg.str();
|
if (write(fFd, str.c_str(), str.length()) < 0) nerr += 1;
|
if (write(fFd, str.c_str(), str.length()) < 0) nerr += 1;
|
}
|
}
|
|
|
|
// send chars buffered while attached but not connected
|
|
if (nerr==0 && fSndPreConQue.size()) {
|
|
stringstream msg;
|
|
while (!fSndPreConQue.empty()) {
|
|
msg << char(fSndPreConQue.front());
|
|
fSndPreConQue.pop_front();
|
|
}
|
|
string str = msg.str();
|
|
if (write(fFd, str.c_str(), str.length()) < 0) nerr += 1;
|
|
}
|
|
|
if (nerr) {
|
if (nerr) {
|
close(fFd);
|
close(fFd);
|
fFd = -1;
|
fFd = -1;
|
RlogMsg lmsg(LogFile(),'E');
|
RlogMsg lmsg(LogFile(),'E');
|
RerrMsg emsg("Rw11VirtTermTcp::ListenPollHandler",
|
RerrMsg emsg("Rw11VirtTermTcp::ListenPollHandler",
|