mirror of
https://projects.vdr-developer.org/git/vdr-plugin-streamdev.git
synced 2023-10-10 17:16:51 +00:00
Snapshot 2007-03-20
This commit is contained in:
49
tools/select.c
Normal file
49
tools/select.c
Normal 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
75
tools/select.h
Normal 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
143
tools/socket.c
Normal 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
108
tools/socket.h
Normal 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
169
tools/source.c
Normal 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
109
tools/source.h
Normal 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
12
tools/tools.c
Normal 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
67
tools/tools.h
Normal 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
|
Reference in New Issue
Block a user