Snapshot 2007-03-20

This commit is contained in:
Frank Schmirler
2010-12-02 08:53:01 +01:00
commit 5e30711bfd
97 changed files with 21652 additions and 0 deletions

49
tools/select.c Normal file
View File

@@ -0,0 +1,49 @@
#include "tools/select.h"
#include <vdr/tools.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <errno.h>
cTBSelect::cTBSelect(void) {
Clear();
}
cTBSelect::~cTBSelect() {
}
int cTBSelect::Select(uint TimeoutMs) {
struct timeval tv;
ssize_t res;
int ms;
tv.tv_usec = (TimeoutMs % 1000) * 1000;
tv.tv_sec = TimeoutMs / 1000;
if (TimeoutMs == 0)
return ::select(m_MaxFiled + 1, &m_Rfds, &m_Wfds, NULL, &tv);
cTimeMs starttime;
ms = TimeoutMs;
while (ms > 0 && (res = ::select(m_MaxFiled + 1, &m_Rfds, &m_Wfds, NULL,
&tv)) == -1 && errno == EINTR) {
ms = TimeoutMs - starttime.Elapsed();
tv.tv_usec = (ms % 1000) * 1000;
tv.tv_sec = ms / 1000;
}
if (ms <= 0) {
errno = ETIMEDOUT;
return -1;
}
return res;
}
int cTBSelect::Select(void) {
ssize_t res;
while ((res = ::select(m_MaxFiled + 1, &m_Rfds, &m_Wfds, NULL, NULL)) == -1
&& errno == EINTR)
;
return res;
}

75
tools/select.h Normal file
View File

@@ -0,0 +1,75 @@
#ifndef TOOLBOX_SELECT_H
#define TOOLBOX_SELECT_H
#include "tools/tools.h"
#include <sys/types.h>
/* cTBSelect provides an interface for polling UNIX-like file descriptors. */
class cTBSelect {
private:
int m_MaxFiled;
fd_set m_Rfds;
fd_set m_Wfds;
public:
cTBSelect(void);
virtual ~cTBSelect();
/* Clear() resets the object for use in a new Select() call. All file
descriptors and their previous states are invalidated. */
virtual void Clear(void);
/* Add() adds a file descriptor to be polled in the next Select() call.
That call polls if the file is readable if Output is set to false,
writeable otherwise. */
virtual bool Add(int Filed, bool Output = false);
/* Select() polls all descriptors added by Add() and returns as soon as
one of those changes state (gets readable/writeable), or after
TimeoutMs milliseconds, whichever happens first. It returns the number
of filedescriptors that have changed state. On error, -1 is returned
and errno is set appropriately. */
virtual int Select(uint TimeoutMs);
/* Select() polls all descriptors added by Add() and returns as soon as
one of those changes state (gets readable/writeable). It returns the
number of filedescriptors that have changed state. On error, -1 is
returned and errno is set appropriately. */
virtual int Select(void);
/* CanRead() returns true if the descriptor has changed to readable during
the last Select() call. Otherwise false is returned. */
virtual bool CanRead(int FileNo) const;
/* CanWrite() returns true if the descriptor has changed to writeable
during the last Select() call. Otherwise false is returned. */
virtual bool CanWrite(int FileNo) const;
};
inline void cTBSelect::Clear(void) {
FD_ZERO(&m_Rfds);
FD_ZERO(&m_Wfds);
m_MaxFiled = -1;
}
inline bool cTBSelect::Add(int Filed, bool Output /* = false */) {
if (Filed < 0) return false;
FD_SET(Filed, Output ? &m_Wfds : &m_Rfds);
if (Filed > m_MaxFiled) m_MaxFiled = Filed;
return true;
}
inline bool cTBSelect::CanRead(int FileNo) const {
if (FileNo < 0) return false;
return FD_ISSET(FileNo, &m_Rfds);
}
inline bool cTBSelect::CanWrite(int FileNo) const {
if (FileNo < 0) return false;
return FD_ISSET(FileNo, &m_Wfds);
}
#endif // TOOLBOX_SELECT_H

143
tools/socket.c Normal file
View File

@@ -0,0 +1,143 @@
#include "tools/socket.h"
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
cTBSocket::cTBSocket(int Type) {
memset(&m_LocalAddr, 0, sizeof(m_LocalAddr));
memset(&m_RemoteAddr, 0, sizeof(m_RemoteAddr));
m_Type = Type;
}
cTBSocket::~cTBSocket() {
if (IsOpen()) Close();
}
bool cTBSocket::Connect(const std::string &Host, unsigned int Port) {
socklen_t len;
int socket;
if (IsOpen()) Close();
if ((socket = ::socket(PF_INET, m_Type, IPPROTO_IP)) == -1)
return false;
m_LocalAddr.sin_family = AF_INET;
m_LocalAddr.sin_port = 0;
m_LocalAddr.sin_addr.s_addr = INADDR_ANY;
if (::bind(socket, (struct sockaddr*)&m_LocalAddr, sizeof(m_LocalAddr))
== -1) {
::close(socket);
return false;
}
m_RemoteAddr.sin_family = AF_INET;
m_RemoteAddr.sin_port = htons(Port);
m_RemoteAddr.sin_addr.s_addr = inet_addr(Host.c_str());
if (::connect(socket, (struct sockaddr*)&m_RemoteAddr,
sizeof(m_RemoteAddr)) == -1) {
::close(socket);
return false;
}
len = sizeof(struct sockaddr_in);
if (::getpeername(socket, (struct sockaddr*)&m_RemoteAddr, &len) == -1) {
::close(socket);
return false;
}
len = sizeof(struct sockaddr_in);
if (::getsockname(socket, (struct sockaddr*)&m_LocalAddr, &len) == -1) {
::close(socket);
return false;
}
return cTBSource::Open(socket);
}
bool cTBSocket::Listen(const std::string &Ip, unsigned int Port, int BackLog) {
int val;
socklen_t len;
int socket;
if (IsOpen()) Close();
if ((socket = ::socket(PF_INET, m_Type, IPPROTO_IP)) == -1)
return false;
val = 1;
if (::setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) == -1)
return false;
m_LocalAddr.sin_family = AF_INET;
m_LocalAddr.sin_port = htons(Port);
m_LocalAddr.sin_addr.s_addr = inet_addr(Ip.c_str());
if (::bind(socket, (struct sockaddr*)&m_LocalAddr, sizeof(m_LocalAddr))
== -1)
return false;
len = sizeof(struct sockaddr_in);
if (::getsockname(socket, (struct sockaddr*)&m_LocalAddr, &len) == -1)
return false;
if (m_Type == SOCK_STREAM && ::listen(socket, BackLog) == -1)
return false;
if (!cTBSource::Open(socket))
return false;
return true;
}
bool cTBSocket::Accept(const cTBSocket &Listener) {
socklen_t addrlen;
int socket;
if (IsOpen()) Close();
addrlen = sizeof(struct sockaddr_in);
if ((socket = ::accept(Listener, (struct sockaddr*)&m_RemoteAddr,
&addrlen)) == -1)
return false;
addrlen = sizeof(struct sockaddr_in);
if (::getsockname(socket, (struct sockaddr*)&m_LocalAddr, &addrlen) == -1)
return false;
if (!cTBSource::Open(socket))
return false;
return true;
}
RETURNS(cTBSocket, cTBSocket::Accept(void) const, ret)
ret.Accept(*this);
RETURN(ret)
bool cTBSocket::Close(void) {
bool ret = true;
if (!IsOpen())
ERRNUL(EBADF);
if (::close(*this) == -1)
ret = false;
if (!cTBSource::Close())
ret = false;
memset(&m_LocalAddr, 0, sizeof(m_LocalAddr));
memset(&m_RemoteAddr, 0, sizeof(m_RemoteAddr));
return ret;
}
bool cTBSocket::Shutdown(int how) {
if (!IsOpen())
ERRNUL(EBADF);
return ::shutdown(*this, how) != -1;
}

108
tools/socket.h Normal file
View File

@@ -0,0 +1,108 @@
#ifndef TOOLBOX_SOCKET_H
#define TOOLBOX_SOCKET_H
#include "tools/tools.h"
#include "tools/source.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string>
/* cTBSocket provides a cTBSource-derived interface for input and output on
TCP/IPv4-sockets. */
class cTBSocket: public cTBSource {
private:
struct sockaddr_in m_LocalAddr;
struct sockaddr_in m_RemoteAddr;
int m_Type;
public:
cTBSocket(int Type = SOCK_STREAM);
virtual ~cTBSocket();
/* See cTBSource::SysRead()
Reimplemented for TCP/IPv4 sockets. */
virtual ssize_t SysRead(void *Buffer, size_t Length) const;
/* See cTBSource::SysWrite()
Reimplemented for TCP/IPv4 sockets. */
virtual ssize_t SysWrite(const void *Buffer, size_t Length) const;
/* Connect() tries to connect an available local socket to the port given
by Port of the target host given by Host in numbers-and-dots notation
(i.e. "212.43.45.21"). Returns true if the connection attempt was
successful and false otherwise, setting errno appropriately. */
virtual bool Connect(const std::string &Host, uint Port);
/* Shutdown() shuts down one or both ends of a socket. If called with How
set to SHUT_RD, further reads on this socket will be denied. If called
with SHUT_WR, all writes are denied. Called with SHUT_RDWR, all firther
action on this socket will be denied. Returns true on success and false
otherwise, setting errno appropriately. */
virtual bool Shutdown(int How);
/* Close() closes the associated socket and releases all structures.
Returns true on success and false otherwise, setting errno
appropriately. The object is in the closed state afterwards, regardless
of any errors. */
virtual bool Close(void);
/* Listen() listens on the local port Port for incoming connections. The
BackLog parameter defines the maximum length the queue of pending
connections may grow to. Returns true if the object is listening on
the specified port and false otherwise, setting errno appropriately. */
virtual bool Listen(const std::string &Ip, uint Port, int BackLog);
/* Accept() returns a newly created cTBSocket, which is connected to the
first connection request on the queue of pending connections of a
listening socket. If no connection request was pending, or if any other
error occured, the resulting cTBSocket is closed. */
virtual cTBSocket Accept(void) const;
/* Accept() extracts the first connection request on the queue of pending
connections of the listening socket Listener and connects it to this
object. Returns true on success and false otherwise, setting errno to
an appropriate value. */
virtual bool Accept(const cTBSocket &Listener);
/* LocalPort() returns the port number this socket is connected to locally.
The result is undefined for a non-open socket. */
int LocalPort(void) const { return ntohs(m_LocalAddr.sin_port); }
/* RemotePort() returns the port number this socket is connected to on the
remote side. The result is undefined for a non-open socket. */
int RemotePort(void) const { return ntohs(m_RemoteAddr.sin_port); }
/* LocalIp() returns the internet address in numbers-and-dots notation of
the interface this socket is connected to locally. This can be
"0.0.0.0" for a listening socket listening to all interfaces. If the
socket is in its closed state, the result is undefined. */
std::string LocalIp(void) const { return inet_ntoa(m_LocalAddr.sin_addr); }
/* RemoteIp() returns the internet address in numbers-and-dots notation of
the interface this socket is connected to on the remote side. If the
socket is in its closed state, the result is undefined. */
std::string RemoteIp(void) const { return inet_ntoa(m_RemoteAddr.sin_addr); }
in_addr_t LocalIpAddr(void) const { return m_LocalAddr.sin_addr.s_addr; }
in_addr_t RemoteIpAddr(void) const { return m_RemoteAddr.sin_addr.s_addr; }
int Type(void) const { return m_Type; }
};
inline ssize_t cTBSocket::SysRead(void *Buffer, size_t Length) const {
if (m_Type == SOCK_DGRAM) {
socklen_t len = sizeof(m_RemoteAddr);
return ::recvfrom(*this, Buffer, Length, 0, (sockaddr*)&m_RemoteAddr, &len);
} else
return ::recv(*this, Buffer, Length, 0);
}
inline ssize_t cTBSocket::SysWrite(const void *Buffer, size_t Length) const {
return ::send(*this, Buffer, Length, 0);
}
#endif // TOOLBOX_SOCKET_H

169
tools/source.c Normal file
View File

@@ -0,0 +1,169 @@
#include "tools/source.h"
#include "tools/select.h"
#include "common.h"
#include <vdr/tools.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
cTBSource::cTBSource(void) {
m_BytesRead = 0;
m_BytesWritten = 0;
m_Filed = -1;
}
bool cTBSource::Open(int Filed, bool IsUnixFd) {
if (IsOpen())
Close();
m_Filed = Filed;
if (IsUnixFd && ::fcntl(m_Filed, F_SETFL, O_NONBLOCK) == -1)
return false;
return true;
}
cTBSource::~cTBSource() {
}
bool cTBSource::Close(void) {
if (!IsOpen()) {
errno = EBADF;
return false;
}
m_Filed = -1;
return true;
}
ssize_t cTBSource::Read(void *Buffer, size_t Length) {
ssize_t res;
while ((res = SysRead(Buffer, Length)) < 0 && errno == EINTR)
errno = 0;
if (res > 0) m_BytesRead += res;
return res;
}
ssize_t cTBSource::Write(const void *Buffer, size_t Length) {
ssize_t res;
while ((res = SysWrite(Buffer, Length)) < 0 && errno == EINTR)
errno = 0;
if (res > 0) m_BytesWritten += res;
return res;
}
bool cTBSource::TimedWrite(const void *Buffer, size_t Length, uint TimeoutMs) {
cTBSelect sel;
int ms, offs;
cTimeMs starttime;
ms = TimeoutMs;
offs = 0;
while (Length > 0) {
int b;
sel.Clear();
sel.Add(m_Filed, true);
if (sel.Select(ms) == -1)
return false;
if (sel.CanWrite(m_Filed)) {
if ((b = Write((char*)Buffer + offs, Length)) == -1)
return false;
offs += b;
Length -= b;
}
ms = TimeoutMs - starttime.Elapsed();
if (ms <= 0) {
errno = ETIMEDOUT;
return false;
}
}
return true;
}
bool cTBSource::SafeWrite(const void *Buffer, size_t Length) {
cTBSelect sel;
int offs;
offs = 0;
while (Length > 0) {
int b;
sel.Clear();
sel.Add(m_Filed, true);
if (sel.Select() == -1)
return false;
if (sel.CanWrite(m_Filed)) {
if ((b = Write((char*)Buffer + offs, Length)) == -1)
return false;
offs += b;
Length -= b;
}
}
return true;
}
ssize_t cTBSource::ReadUntil(void *Buffer, size_t Length, const char *Seq,
uint TimeoutMs) {
int seqlen, ms;
size_t len;
cTBSelect sel;
if ((len = m_LineBuffer.find(Seq)) != (size_t)-1) {
if (len > Length) {
errno = ENOBUFS;
return -1;
}
memcpy(Buffer, m_LineBuffer.data(), len);
m_LineBuffer.erase(0, len + strlen(Seq));
Dprintf("ReadUntil: Served from Linebuffer: %d, |%.*s|\n", len, len - 1,
(char*)Buffer);
return len;
}
cTimeMs starttime;
ms = TimeoutMs;
while (m_LineBuffer.size() < BUFSIZ) {
sel.Clear();
sel.Add(m_Filed, false);
if (sel.Select(ms) == -1)
return -1;
if (sel.CanRead(m_Filed)) {
int b;
len = m_LineBuffer.size();
m_LineBuffer.resize(BUFSIZ);
if ((b = Read((char*)m_LineBuffer.data() + len, BUFSIZ - len)) == -1)
return -1;
m_LineBuffer.resize(len + b);
if ((len = m_LineBuffer.find(Seq)) != (size_t)-1) {
if (len > Length) {
errno = ENOBUFS;
return -1;
}
memcpy(Buffer, m_LineBuffer.data(), len);
m_LineBuffer.erase(0, len + strlen(Seq));
Dprintf("ReadUntil: Served from Linebuffer: %d, |%.*s|\n", len, len - 1,
(char*)Buffer);
return len;
}
}
ms = TimeoutMs - starttime.Elapsed();
if (ms <= 0) {
errno = ETIMEDOUT;
return -1;
}
}
errno = ENOBUFS;
return -1;
}

109
tools/source.h Normal file
View File

@@ -0,0 +1,109 @@
#ifndef TOOLBOX_SOURCE_H
#define TOOLBOX_SOURCE_H
#include "tools/tools.h"
#include <sys/types.h>
#include <string>
/* cTBSource provides an abstract interface for input and output. It can
be used to have common access to different types of UNIX-files. */
class cTBSource {
private:
int m_Filed;
size_t m_BytesRead;
size_t m_BytesWritten;
std::string m_LineBuffer;
public:
cTBSource(void);
virtual ~cTBSource();
/* SysRead() implements the low-level read on the source. It will store
data into the area pointed to by Buffer, which is at least Length
bytes in size. It will return the exact number of bytes read (which
can be fewer than requested). On error, -1 is returned, and errno
is set to an appropriate value. */
virtual ssize_t SysRead(void *Buffer, size_t Length) const = 0;
/* SysWrite() implements the low-level write on the source. It will write
at most Length bytes of the data pointed to by Buffer. It will return
the exact number of bytes written (which can be fewer than requested).
On error, -1 is returned, and errno is set to an appropriate value. */
virtual ssize_t SysWrite(const void *Buffer, size_t Length) const = 0;
/* IsOpen() returns true, if this source refers to a valid descriptor.
It is not checked whether this source is really open, so only if
opened by the appropriate Methods this function will return the
correct value */
virtual bool IsOpen(void) const { return m_Filed != -1; }
/* Open() associates this source with the descriptor Filed, setting it
to non-blocking mode if IsUnixFd in true. Returns true on success,
and false on error, setting errno to appropriately.
If you want to implement sources that can't be represented by UNIX
filedescriptors, you can use Filed to store any useful information
about the source.
This must be called by any derivations in an appropriate Method (like
open for files, connect for sockets). */
virtual bool Open(int Filed, bool IsUnixFd = true);
/* Close() resets the source to the uninitialized state (IsOpen() == false)
and must be called by any derivations after really closing the source.
Returns true on success and false on error, setting errno appropriately.
The object is in closed state afterwards, even if an error occured. */
virtual bool Close(void);
/* Read() reads at most Length bytes into the storage pointed to by Buffer,
which must be at least Length bytes in size, using the SysRead()-
Interface. It retries if an EINTR occurs (i.e. the low-level call was
interrupted). It returns the exact number of bytes read (which can be
fewer than requested). On error, -1 is returned, and errno is set
appropriately. */
ssize_t Read(void *Buffer, size_t Length);
/* Write() writes at most Length bytes from the storage pointed to by
Buffer, using the SysWrite()-Interface. It retries if EINTR occurs
(i.e. the low-level call was interrupted). It returns the exact number
of bytes written (which can be fewer than requested). On error, -1 is
returned and errno is set appropriately. */
ssize_t Write(const void *Buffer, size_t Length);
/* TimedWrite() tries to write Length bytes from the storage pointed to by
Buffer within the time specified by TimeoutMs, using the Write()-
Interface. On success, true is returned. On error, false is returned
and errno is set appropriately. TimedRead only works on UNIX file
descriptor sources. */
bool TimedWrite(const void *Buffer, size_t Length, uint TimeoutMs);
bool SafeWrite(const void *Buffer, size_t Length);
/* ReadUntil() tries to read at most Length bytes into the storage pointed
to by Buffer, which must be at least Length bytes in size, within the
time specified by TimeoutMs, using the Read()-Interface. Reading stops
after the character sequence Seq has been read and on end-of-file.
Returns the number of bytes read (if that is equal to Length, you have
to check if the buffer ends with Seq), or -1 on error, in which case
errno is set appropriately. */
ssize_t ReadUntil(void *Buffer, size_t Length, const char *Seq,
uint TimeoutMs);
/* BytesRead() returns the exact number of bytes read through the Read()
method since Close() has been called on this source (or since its
creation). */
size_t BytesRead(void) const { return m_BytesRead; }
/* BytesWritten() returns the exact number of bytes written through the
Write() method since Close() has been called on this source (or since
its creation). */
size_t BytesWritten(void) const { return m_BytesWritten; }
/* operator int() returns the descriptor (or informative number) associated
with this source. */
operator int() const { return m_Filed; }
};
#endif // TOOLBOX_SOURCE_H

12
tools/tools.c Normal file
View File

@@ -0,0 +1,12 @@
#include "tools/tools.h"
#include <sys/time.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdarg.h>
void *operator new(size_t nSize, void *p) throw () {
return p;
}

67
tools/tools.h Normal file
View File

@@ -0,0 +1,67 @@
#ifndef TOOLBOX_TOOLS_H
#define TOOLBOX_TOOLS_H
//#include <stdio.h>
//#include <iostream>
#include <sys/types.h>
//#define KILOBYTE(x) ((x)*1024)
//#define MEGABYTE(x) (KILOBYTE(x)*1024)
//typedef unsigned int uint;
//typedef unsigned long ulong;
typedef unsigned char uchar;
//typedef unsigned short ushort;
// Special constructor for CreateElements
void *operator new(size_t, void*) throw ();
#ifdef TOOLBOX_DEBUG
# define ASSERT(x) if ((x)) cerr << "Warning: ASSERT failed At " << __FILE__ << ":" << __LINE__ << " ["#x"]" << endl
# define CHECK_PTR(x) if (!(x)) cerr << "Warning: Pointer is NULL At " << __FILE__ << ":" << __LINE__ << endl;
# define CHECK_NEXT_ALLOC() _checkNextAlloc()
# define DPRINT(x...) LOGi(x)
#else
# define ASSERT(x)
# define CHECK_PTR(x)
# define CHECK_NEXT_ALLOC()
# define DPRINT(x...)
#endif
#define ERRNUL(e) {errno=e;return 0;}
#define ERRSYS(e) {errno=e;return -1;}
/* RETURNS() and RETURN() are macros that can be used if a class object is
being returned. They make use of the GNU C-Compiler's named return value
feature, if available. In this case, the class object isn't returned and
copied, but the result itself is filled.
RETURNS(ReturnType, FunctionDeclaration, Result)
... function-body working on Result ...
RETURN(Result)
A function like this (cXYZ is a class type):
cXYZ myfunction(int a, char *b) {
cXYZ result;
... something happens with result ...
return result;
}
can be written like this:
RETURNS(cXYZ, myfunction(int a, char *b), result)
... something happens with result ...
RETURN(result)
DISABLED SINCE GCC 3.x
*/
//#ifdef __GNUC__
//# define RETURNS(t,x,r) t x return r {
//# define RETURN(x) }
//#else
# define RETURNS(t,x,r) t x { t r;
# define RETURN(x) return x; }
//#endif
#endif // TOOLBOX_TOOLS_H