SVDRP now also works with clients that don't do line buffering

This commit is contained in:
Klaus Schmidinger 2001-04-01 14:13:42 +02:00
parent 28130daef7
commit ab626eecd3
5 changed files with 55 additions and 44 deletions

View File

@ -447,3 +447,6 @@ Video Disk Recorder Revision History
- Fixed a segfault that sometimes happened when killing VDR. - Fixed a segfault that sometimes happened when killing VDR.
- VDR now returns an exit status of '2' in case of an error at startup, instead - VDR now returns an exit status of '2' in case of an error at startup, instead
of terminating with 'abort()' (which caused a core dump). of terminating with 'abort()' (which caused a core dump).
- SVDRP now also works with clients that don't do line buffering (like the
Windows 'telnet').

64
svdrp.c
View File

@ -10,7 +10,7 @@
* and interact with the Video Disk Recorder - or write a full featured * and interact with the Video Disk Recorder - or write a full featured
* graphical interface that sits on top of an SVDRP connection. * graphical interface that sits on top of an SVDRP connection.
* *
* $Id: svdrp.c 1.15 2001/03/02 22:59:37 kls Exp $ * $Id: svdrp.c 1.16 2001/04/01 14:09:29 kls Exp $
*/ */
#define _GNU_SOURCE #define _GNU_SOURCE
@ -113,7 +113,6 @@ int cSocket::Accept(void)
// --- cSVDRP ---------------------------------------------------------------- // --- cSVDRP ----------------------------------------------------------------
#define MAXCMDBUFFER 10000
#define MAXHELPTOPIC 10 #define MAXHELPTOPIC 10
const char *HelpPages[] = { const char *HelpPages[] = {
@ -234,6 +233,7 @@ const char *GetHelpPage(const char *Cmd)
cSVDRP::cSVDRP(int Port) cSVDRP::cSVDRP(int Port)
:socket(Port) :socket(Port)
{ {
numChars = 0;
message = NULL; message = NULL;
lastActivity = 0; lastActivity = 0;
isyslog(LOG_INFO, "SVDRP listening on port %d", Port); isyslog(LOG_INFO, "SVDRP listening on port %d", Port);
@ -842,7 +842,8 @@ void cSVDRP::Execute(char *Cmd)
char *s = Cmd; char *s = Cmd;
while (*s && !isspace(*s)) while (*s && !isspace(*s))
s++; s++;
*s++ = 0; if (*s)
*s++ = 0;
if (CMD("CHAN")) CmdCHAN(s); if (CMD("CHAN")) CmdCHAN(s);
else if (CMD("DELC")) CmdDELC(s); else if (CMD("DELC")) CmdDELC(s);
else if (CMD("DELT")) CmdDELT(s); else if (CMD("DELT")) CmdDELT(s);
@ -864,8 +865,7 @@ void cSVDRP::Execute(char *Cmd)
else if (CMD("OVLP")) CmdOVLP(s); else if (CMD("OVLP")) CmdOVLP(s);
else if (CMD("OVLO")) CmdOVLO(s); else if (CMD("OVLO")) CmdOVLO(s);
else if (CMD("UPDT")) CmdUPDT(s); else if (CMD("UPDT")) CmdUPDT(s);
else if (CMD("QUIT") else if (CMD("QUIT")) Close();
|| CMD("\x04")) Close();
else Reply(500, "Command unrecognized: \"%s\"", Cmd); else Reply(500, "Command unrecognized: \"%s\"", Cmd);
} }
@ -875,29 +875,55 @@ void cSVDRP::Process(void)
bool SendGreeting = NewConnection; bool SendGreeting = NewConnection;
if (file.IsOpen() || file.Open(socket.Accept())) { if (file.IsOpen() || file.Open(socket.Accept())) {
char buffer[MAXCMDBUFFER];
if (SendGreeting) { if (SendGreeting) {
//TODO how can we get the *full* hostname? //TODO how can we get the *full* hostname?
char buffer[MAXCMDBUFFER];
gethostname(buffer, sizeof(buffer)); gethostname(buffer, sizeof(buffer));
time_t now = time(NULL); time_t now = time(NULL);
Reply(220, "%s SVDRP VideoDiskRecorder %s; %s", buffer, VDRVERSION, ctime(&now)); Reply(220, "%s SVDRP VideoDiskRecorder %s; %s", buffer, VDRVERSION, ctime(&now));
} }
if (NewConnection) if (NewConnection)
lastActivity = time(NULL); lastActivity = time(NULL);
int rbytes = file.ReadString(buffer, sizeof(buffer) - 1); if (file.Ready(false)) {
if (rbytes > 0) { unsigned char c;
//XXX overflow check??? int r = read(file, &c, 1);
// strip trailing whitespace: if (r > 0) {
while (rbytes > 0 && strchr(" \t\r\n", buffer[rbytes - 1])) if (c == '\n' || c == 0x00) {
buffer[--rbytes] = 0; // strip trailing whitespace:
// make sure the string is terminated: while (numChars > 0 && strchr(" \t\r\n", cmdLine[numChars - 1]))
buffer[rbytes] = 0; cmdLine[--numChars] = 0;
// showtime! // make sure the string is terminated:
Execute(buffer); cmdLine[numChars] = 0;
lastActivity = time(NULL); // showtime!
Execute(cmdLine);
numChars = 0;
}
else if (c == 0x04 && numChars == 0) {
// end of file (only at beginning of line)
Close();
}
else if (c == 0x08 || c == 0x7F) {
// backspace or delete (last character)
if (numChars > 0)
numChars--;
}
else if (c <= 0x03 || c == 0x0D || 0xF0 <= c) {
// ignore control characters
}
else if (numChars < sizeof(cmdLine) - 1) {
cmdLine[numChars++] = c;
cmdLine[numChars] = 0;
}
else {
Reply(501, "Command line too long");
esyslog(LOG_ERR, "SVDRP: command line too long: '%s'", cmdLine);
numChars = 0;
}
lastActivity = time(NULL);
}
else if (r < 0)
Close();
} }
else if (rbytes < 0)
Close();
else if (Setup.SVDRPTimeout && time(NULL) - lastActivity > Setup.SVDRPTimeout) { else if (Setup.SVDRPTimeout && time(NULL) - lastActivity > Setup.SVDRPTimeout) {
isyslog(LOG_INFO, "timeout on SVDRP connection"); isyslog(LOG_INFO, "timeout on SVDRP connection");
Close(true); Close(true);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: svdrp.h 1.7 2001/02/18 13:36:47 kls Exp $ * $Id: svdrp.h 1.8 2001/04/01 14:10:33 kls Exp $
*/ */
#ifndef __SVDRP_H #ifndef __SVDRP_H
@ -26,11 +26,15 @@ public:
int Accept(void); int Accept(void);
}; };
#define MAXCMDBUFFER 1024
class cSVDRP { class cSVDRP {
private: private:
cSocket socket; cSocket socket;
cFile file; cFile file;
CRect ovlClipRects[MAXCLIPRECTS]; CRect ovlClipRects[MAXCLIPRECTS];
uint numChars;
char cmdLine[MAXCMDBUFFER];
char *message; char *message;
time_t lastActivity; time_t lastActivity;
void Close(bool Timeout = false); void Close(bool Timeout = false);

23
tools.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: tools.c 1.31 2001/03/03 13:25:00 kls Exp $ * $Id: tools.c 1.32 2001/04/01 14:13:36 kls Exp $
*/ */
#define _GNU_SOURCE #define _GNU_SOURCE
@ -369,27 +369,6 @@ void cFile::Close(void)
} }
} }
int cFile::ReadString(char *Buffer, int Size)
{
int rbytes = 0;
bool wait = true;
while (Ready(wait)) {
int n = read(f, Buffer + rbytes, 1);
if (n == 0)
break; // EOF
if (n < 0) {
LOG_ERROR;
return -1;
}
rbytes += n;
if (rbytes == Size || Buffer[rbytes - 1] == '\n')
break;
wait = false;
}
return rbytes;
}
bool cFile::Ready(bool Wait) bool cFile::Ready(bool Wait)
{ {
return f >= 0 && AnyFileReady(f, Wait ? 1000 : 0); return f >= 0 && AnyFileReady(f, Wait ? 1000 : 0);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: tools.h 1.24 2001/02/11 13:39:40 kls Exp $ * $Id: tools.h 1.25 2001/04/01 14:13:42 kls Exp $
*/ */
#ifndef __TOOLS_H #ifndef __TOOLS_H
@ -64,7 +64,6 @@ public:
bool Open(int FileDes); bool Open(int FileDes);
void Close(void); void Close(void);
bool IsOpen(void) { return f >= 0; } bool IsOpen(void) { return f >= 0; }
int ReadString(char *Buffer, int Size);
bool Ready(bool Wait = true); bool Ready(bool Wait = true);
static bool AnyFileReady(int FileDes = -1, int TimeoutMs = 1000); static bool AnyFileReady(int FileDes = -1, int TimeoutMs = 1000);
static bool FileReady(int FileDes, int TimeoutMs = 1000); static bool FileReady(int FileDes, int TimeoutMs = 1000);