23 #include "common_priv.h"
51 std::vector<FileHandle*> fds;
58 ClientMap::iterator itr =
clients.begin();
61 if (client->Closed()) {
62 ClientMap::iterator todelete = itr;
67 if (client->Readable()) {
70 fds.push_back(client.get());
77 Poll(fds.begin(), fds.end(), -1);
85 ClientMap::iterator itr =
clients.begin();
88 if (!client->Closed()) {
90 client->ShutdownWrite();
100 dbprintf(1,
"Terminating %s\n", name.c_str());
108 clients.insert(std::make_pair(conn->GetName(), conn));
115 dbprintf(1,
"Trying to send a reply after shutdown\n%s:%s",
116 recipient.c_str(), libvariant::SerializeJSON(msg).c_str());
119 ClientMap::iterator entry =
clients.find(recipient);
121 dbprintf(4,
"reply:%s:%s\n", recipient.c_str(), libvariant::SerializeJSON(msg).c_str());
122 entry->second->Send(msg);
127 dbprintf(1,
"Trying to braodcast after shutdown\n%s", libvariant::SerializeJSON(msg).c_str());
130 ClientMap::iterator entry =
clients.begin();
131 dbprintf(4,
"broadcast:%s\n", libvariant::SerializeJSON(msg).c_str());
132 while (entry !=
clients.end()) {
133 entry->second->Send(msg);
139 dbprintf(1,
"log:%s\n", msg.c_str());
150 d->
dbprintf(1,
"New connection from %s\n",
name.c_str());
154 std::vector<char> buf(4*1024);
158 if (buf.size() - num <= 0) {
159 buf.resize(buf.size()*2);
161 unsigned numread = Recv(&buf[num], buf.size() - num,
false);
164 daemon->Terminate(name);
169 char *end = (
char*)memchr(&buf[0], 0, num);
171 Variant v = libvariant::DeserializeJSON(&buf[0]);
172 daemon->DispatchMessage(name, v);
174 num -= (end - &buf[0]);
175 memmove(&buf[0], end, num);
176 end = (
char*)memchr(&buf[0], 0, num);
180 if (!daemon->IsTerminated()) {
181 daemon->dbprintf(1,
"Unable to read from %s:%d: %s\n", name.c_str(), e.
Error(), e.
what());
191 std::string message = libvariant::SerializeJSON(msg);
192 unsigned numwritten = 0;
193 while (numwritten < message.size() + 1) {
194 numwritten +=
Write(message.c_str() + numwritten, (message.size() + 1) - numwritten);
197 daemon->dbprintf(1,
"Unable to write to %s:%d: %s\n", name.c_str(), e.
Error(), e.
what());
198 daemon->Terminate(name);
void LogMessage(const std::string &msg)
Log a message.
Client(RemoteContextDaemon *d, int nfd)
void Listen(const SocketAddress &addr, int queuelength=256)
void Run()
Run the actual Context returns when the context is terminated and all clients have disconnected...
An abstraction of a socket address with convenience methods.
A FileHandle customized with some socket specific functionality and functions.
std::string GetHostName(bool numerichost=true) const
void SetFromPeerName(int fd)
Fill this SocketAddress with data from the other side of the connection represented by fd...
void dbprintf(int level, const char *fmt,...)
static int Poll(IteratorRef< FileHandle * > begin, IteratorRef< FileHandle * > end, double timeout)
poll a list of FileHandles for any activity and call the appropriate On method.
void SetFromSockName(int fd)
Fill this SocketAddress with data from this side of the connection represented by fd...
void Close()
Close the file and reset the internal state.
std::tr1::shared_ptr< Client > ClientPtr
void SetNoDelay(bool nodelay)
std::string GetServName() const
void SetReuseAddr(bool reuse=true)
Turn on reuse of the address. Only takes effect if set before Listen.
bool IsTerminated() const
void BroadcastMessage(const Variant &msg)
Broadcast a message to all clients.
RemoteContextDaemon(const SocketAddress &addr)
std::vector< SocketAddress > SockAddrList
virtual const char * what() const
bool Readable() const
Gives the current readability status of the file.
void SendMessage(const std::string &recipient, const Variant &msg)
Send the given message to the given client.
bool Good() const
Convenience method for testing if the file this FileHandle has is open and not at end of file...
void Send(const Variant &msg)
unsigned Write(const void *ptr, unsigned len)
Write data to the file descriptor.