Update NEWS and UPGRADING for 2.7.1
[networkupstools/kirr.git] / clients / nutclient.cpp
blobdcf0c2da75c3097dea868d92fe77df47b33c31b1
1 /* nutclient.cpp - nutclient C++ library implementation
3 Copyright (C) 2012 Emilien Kia <emilien.kia@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "nutclient.h"
22 #include <sstream>
24 #include <errno.h>
25 #include <string.h>
26 #include <stdio.h>
28 /* Windows/Linux Socket compatibility layer: */
29 /* Thanks to Benjamin Roux (http://broux.developpez.com/articles/c/sockets/) */
30 #ifdef WIN32
31 # include <winsock2.h>
32 #else
33 # include <sys/types.h>
34 # include <sys/socket.h>
35 # include <netinet/in.h>
36 # include <arpa/inet.h>
37 # include <unistd.h> /* close */
38 # include <netdb.h> /* gethostbyname */
39 # include <fcntl.h>
40 # define INVALID_SOCKET -1
41 # define SOCKET_ERROR -1
42 # define closesocket(s) close(s)
43 typedef int SOCKET;
44 typedef struct sockaddr_in SOCKADDR_IN;
45 typedef struct sockaddr SOCKADDR;
46 typedef struct in_addr IN_ADDR;
47 #endif /* WIN32 */
48 /* End of Windows/Linux Socket compatibility layer: */
51 /* Include nut common utility functions or define simple ones if not */
52 #ifdef HAVE_NUTCOMMON
53 #include "common.h"
54 #else /* HAVE_NUTCOMMON */
55 #include <stdlib.h>
56 #include <string.h>
57 static inline void *xmalloc(size_t size){return malloc(size);}
58 static inline void *xcalloc(size_t number, size_t size){return calloc(number, size);}
59 static inline void *xrealloc(void *ptr, size_t size){return realloc(ptr, size);}
60 static inline char *xstrdup(const char *string){return strdup(string);}
61 #endif /* HAVE_NUTCOMMON */
64 namespace nut
67 SystemException::SystemException():
68 NutException(err())
72 std::string SystemException::err()
74 if(errno==0)
75 return "Undefined system error";
76 else
78 std::stringstream str;
79 str << "System error " << errno << ": " << strerror(errno);
80 return str.str();
85 namespace internal
88 /**
89 * Internal socket wrapper.
90 * Provides only client socket functions.
92 * Implemented as separate internal class to easily hide plateform specificities.
94 class Socket
96 public:
97 Socket();
99 void connect(const std::string& host, int port)throw(nut::IOException);
100 void disconnect();
101 bool isConnected()const;
103 void setTimeout(long timeout);
104 bool hasTimeout()const{return _tv.tv_sec>=0;}
106 size_t read(void* buf, size_t sz)throw(nut::IOException);
107 size_t write(const void* buf, size_t sz)throw(nut::IOException);
109 std::string read()throw(nut::IOException);
110 void write(const std::string& str)throw(nut::IOException);
113 private:
114 SOCKET _sock;
115 struct timeval _tv;
116 std::string _buffer; /* Received buffer, string because data should be text only. */
119 Socket::Socket():
120 _sock(INVALID_SOCKET),
121 _tv()
123 _tv.tv_sec = -1;
124 _tv.tv_usec = 0;
127 void Socket::setTimeout(long timeout)
129 _tv.tv_sec = timeout;
132 void Socket::connect(const std::string& host, int port)throw(nut::IOException)
134 int sock_fd;
135 struct addrinfo hints, *res, *ai;
136 char sport[NI_MAXSERV];
137 int v;
138 fd_set wfds;
139 int error;
140 socklen_t error_size;
141 long fd_flags;
143 _sock = -1;
145 if (host.empty()) {
146 throw nut::UnknownHostException();
149 snprintf(sport, sizeof(sport), "%hu", (unsigned short int)port);
151 memset(&hints, 0, sizeof(hints));
152 hints.ai_family = AF_UNSPEC;
153 hints.ai_socktype = SOCK_STREAM;
154 hints.ai_protocol = IPPROTO_TCP;
156 while ((v = getaddrinfo(host.c_str(), sport, &hints, &res)) != 0) {
157 switch (v)
159 case EAI_AGAIN:
160 continue;
161 case EAI_NONAME:
162 throw nut::UnknownHostException();
163 case EAI_SYSTEM:
164 throw nut::SystemException();
165 case EAI_MEMORY:
166 throw nut::NutException("Out of memory");
167 default:
168 throw nut::NutException("Unknown error");
172 for (ai = res; ai != NULL; ai = ai->ai_next) {
174 sock_fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
176 if (sock_fd < 0) {
177 switch (errno)
179 case EAFNOSUPPORT:
180 case EINVAL:
181 break;
182 default:
183 throw nut::SystemException();
185 continue;
188 /* non blocking connect */
189 if(hasTimeout()) {
190 fd_flags = fcntl(sock_fd, F_GETFL);
191 fd_flags |= O_NONBLOCK;
192 fcntl(sock_fd, F_SETFL, fd_flags);
195 while ((v = ::connect(sock_fd, ai->ai_addr, ai->ai_addrlen)) < 0) {
196 if(errno == EINPROGRESS) {
197 FD_ZERO(&wfds);
198 FD_SET(sock_fd, &wfds);
199 select(sock_fd+1,NULL,&wfds,NULL, hasTimeout()?&_tv:NULL);
200 if (FD_ISSET(sock_fd, &wfds)) {
201 error_size = sizeof(error);
202 getsockopt(sock_fd,SOL_SOCKET,SO_ERROR,
203 &error,&error_size);
204 if( error == 0) {
205 /* connect successful */
206 v = 0;
207 break;
209 errno = error;
211 else {
212 /* Timeout */
213 v = -1;
214 break;
218 switch (errno)
220 case EAFNOSUPPORT:
221 break;
222 case EINTR:
223 case EAGAIN:
224 continue;
225 default:
226 // ups->upserror = UPSCLI_ERR_CONNFAILURE;
227 // ups->syserrno = errno;
228 break;
230 break;
233 if (v < 0) {
234 close(sock_fd);
235 continue;
238 /* switch back to blocking operation */
239 if(hasTimeout()) {
240 fd_flags = fcntl(sock_fd, F_GETFL);
241 fd_flags &= ~O_NONBLOCK;
242 fcntl(sock_fd, F_SETFL, fd_flags);
245 _sock = sock_fd;
246 // ups->upserror = 0;
247 // ups->syserrno = 0;
248 break;
251 freeaddrinfo(res);
253 if (_sock < 0) {
254 throw nut::IOException("Cannot connect to host");
258 #ifdef OLD
259 struct hostent *hostinfo = NULL;
260 SOCKADDR_IN sin = { 0 };
261 hostinfo = ::gethostbyname(host.c_str());
262 if(hostinfo == NULL) /* Host doesnt exist */
264 throw nut::UnknownHostException();
267 // Create socket
268 _sock = ::socket(PF_INET, SOCK_STREAM, 0);
269 if(_sock == INVALID_SOCKET)
271 throw nut::IOException("Cannot create socket");
274 // Connect
275 sin.sin_addr = *(IN_ADDR *) hostinfo->h_addr;
276 sin.sin_port = htons(port);
277 sin.sin_family = AF_INET;
278 if(::connect(_sock,(SOCKADDR *) &sin, sizeof(SOCKADDR)) == SOCKET_ERROR)
280 _sock = INVALID_SOCKET;
281 throw nut::IOException("Cannot connect to host");
283 #endif // OLD
286 void Socket::disconnect()
288 if(_sock != INVALID_SOCKET)
290 ::closesocket(_sock);
291 _sock = INVALID_SOCKET;
293 _buffer.clear();
296 bool Socket::isConnected()const
298 return _sock!=INVALID_SOCKET;
301 size_t Socket::read(void* buf, size_t sz)throw(nut::IOException)
303 if(!isConnected())
305 throw nut::NotConnectedException();
308 if(_tv.tv_sec>=0)
310 fd_set fds;
311 FD_ZERO(&fds);
312 FD_SET(_sock, &fds);
313 int ret = select(_sock+1, &fds, NULL, NULL, &_tv);
314 if (ret < 1) {
315 throw nut::TimeoutException();
319 ssize_t res = ::read(_sock, buf, sz);
320 if(res==-1)
322 disconnect();
323 throw nut::IOException("Error while reading on socket");
325 return (size_t) res;
328 size_t Socket::write(const void* buf, size_t sz)throw(nut::IOException)
330 if(!isConnected())
332 throw nut::NotConnectedException();
335 if(_tv.tv_sec>=0)
337 fd_set fds;
338 FD_ZERO(&fds);
339 FD_SET(_sock, &fds);
340 int ret = select(_sock+1, NULL, &fds, NULL, &_tv);
341 if (ret < 1) {
342 throw nut::TimeoutException();
346 ssize_t res = ::write(_sock, buf, sz);
347 if(res==-1)
349 disconnect();
350 throw nut::IOException("Error while writing on socket");
352 return (size_t) res;
355 std::string Socket::read()throw(nut::IOException)
357 std::string res;
358 char buff[256];
360 while(true)
362 // Look at already read data in _buffer
363 if(!_buffer.empty())
365 size_t idx = _buffer.find('\n');
366 if(idx!=std::string::npos)
368 res += _buffer.substr(0, idx);
369 _buffer.erase(0, idx+1);
370 return res;
372 res += _buffer;
375 // Read new buffer
376 size_t sz = read(&buff, 256);
377 _buffer.assign(buff, sz);
381 void Socket::write(const std::string& str)throw(nut::IOException)
383 // write(str.c_str(), str.size());
384 // write("\n", 1);
385 std::string buff = str + "\n";
386 write(buff.c_str(), buff.size());
389 }/* namespace internal */
394 * Client implementation
398 Client::Client()
402 Client::~Client()
406 bool Client::hasDevice(const std::string& dev)throw(NutException)
408 std::set<std::string> devs = getDeviceNames();
409 return devs.find(dev) != devs.end();
412 Device Client::getDevice(const std::string& name)throw(NutException)
414 if(hasDevice(name))
415 return Device(this, name);
416 else
417 return Device(NULL, "");
420 std::set<Device> Client::getDevices()throw(NutException)
422 std::set<Device> res;
424 std::set<std::string> devs = getDeviceNames();
425 for(std::set<std::string>::iterator it=devs.begin(); it!=devs.end(); ++it)
427 res.insert(Device(this, *it));
430 return res;
433 bool Client::hasDeviceVariable(const std::string& dev, const std::string& name)throw(NutException)
435 std::set<std::string> names = getDeviceVariableNames(dev);
436 return names.find(name) != names.end();
439 std::map<std::string,std::vector<std::string> > Client::getDeviceVariableValues(const std::string& dev)throw(NutException)
441 std::map<std::string,std::vector<std::string> > res;
443 std::set<std::string> names = getDeviceVariableNames(dev);
444 for(std::set<std::string>::iterator it=names.begin(); it!=names.end(); ++it)
446 const std::string& name = *it;
447 res[name] = getDeviceVariableValue(dev, name);
450 return res;
453 bool Client::hasDeviceCommand(const std::string& dev, const std::string& name)throw(NutException)
455 std::set<std::string> names = getDeviceCommandNames(dev);
456 return names.find(name) != names.end();
462 * TCP Client implementation
466 TcpClient::TcpClient():
467 Client(),
468 _host("localhost"),
469 _port(3493),
470 _socket(new internal::Socket)
472 // Do not connect now
475 TcpClient::TcpClient(const std::string& host, int port)throw(IOException):
476 Client(),
477 _socket(new internal::Socket)
479 connect(host, port);
482 TcpClient::~TcpClient()
484 delete _socket;
487 void TcpClient::connect(const std::string& host, int port)throw(IOException)
489 _host = host;
490 _port = port;
491 connect();
494 void TcpClient::connect()throw(nut::IOException)
496 _socket->connect(_host, _port);
499 std::string TcpClient::getHost()const
501 return _host;
504 int TcpClient::getPort()const
506 return _port;
509 bool TcpClient::isConnected()const
511 return _socket->isConnected();
514 void TcpClient::disconnect()
516 _socket->disconnect();
519 void TcpClient::setTimeout(long timeout)
521 _timeout = timeout;
524 long TcpClient::getTimeout()const
526 return _timeout;
529 void TcpClient::authenticate(const std::string& user, const std::string& passwd)
530 throw(NutException)
532 detectError(sendQuery("USERNAME " + user));
533 detectError(sendQuery("PASSWORD " + passwd));
536 void TcpClient::logout()throw(NutException)
538 detectError(sendQuery("LOGOUT"));
539 _socket->disconnect();
542 Device TcpClient::getDevice(const std::string& name)throw(NutException)
546 get("UPSDESC", name);
548 catch(NutException& ex)
550 if(ex.str()=="UNKNOWN-UPS")
551 return Device(NULL, "");
552 else
553 throw;
555 return Device(this, name);
558 std::set<std::string> TcpClient::getDeviceNames()throw(NutException)
560 std::set<std::string> res;
562 std::vector<std::vector<std::string> > devs = list("UPS");
563 for(std::vector<std::vector<std::string> >::iterator it=devs.begin();
564 it!=devs.end(); ++it)
566 std::string id = (*it)[0];
567 if(!id.empty())
568 res.insert(id);
571 return res;
574 std::string TcpClient::getDeviceDescription(const std::string& name)throw(NutException)
576 return get("UPSDESC", name)[0];
579 std::set<std::string> TcpClient::getDeviceVariableNames(const std::string& dev)throw(NutException)
581 std::set<std::string> set;
583 std::vector<std::vector<std::string> > res = list("VAR", dev);
584 for(size_t n=0; n<res.size(); ++n)
586 set.insert(res[n][0]);
589 return set;
592 std::set<std::string> TcpClient::getDeviceRWVariableNames(const std::string& dev)throw(NutException)
594 std::set<std::string> set;
596 std::vector<std::vector<std::string> > res = list("RW", dev);
597 for(size_t n=0; n<res.size(); ++n)
599 set.insert(res[n][0]);
602 return set;
605 std::string TcpClient::getDeviceVariableDescription(const std::string& dev, const std::string& name)throw(NutException)
607 return get("DESC", dev + " " + name)[0];
610 std::vector<std::string> TcpClient::getDeviceVariableValue(const std::string& dev, const std::string& name)throw(NutException)
612 return get("VAR", dev + " " + name);
615 std::map<std::string,std::vector<std::string> > TcpClient::getDeviceVariableValues(const std::string& dev)throw(NutException)
618 std::map<std::string,std::vector<std::string> > map;
620 std::vector<std::vector<std::string> > res = list("VAR", dev);
621 for(size_t n=0; n<res.size(); ++n)
623 std::vector<std::string>& vals = res[n];
624 std::string var = vals[0];
625 vals.erase(vals.begin());
626 map[var] = vals;
629 return map;
632 void TcpClient::setDeviceVariable(const std::string& dev, const std::string& name, const std::string& value)throw(NutException)
634 std::string query = "SET VAR " + dev + " " + name + " " + escape(value);
635 detectError(sendQuery(query));
638 void TcpClient::setDeviceVariable(const std::string& dev, const std::string& name, const std::vector<std::string>& values)throw(NutException)
640 std::string query = "SET VAR " + dev + " " + name;
641 for(size_t n=0; n<values.size(); ++n)
643 query += " " + escape(values[n]);
645 detectError(sendQuery(query));
648 std::set<std::string> TcpClient::getDeviceCommandNames(const std::string& dev)throw(NutException)
650 std::set<std::string> cmds;
652 std::vector<std::vector<std::string> > res = list("CMD", dev);
653 for(size_t n=0; n<res.size(); ++n)
655 cmds.insert(res[n][0]);
658 return cmds;
661 std::string TcpClient::getDeviceCommandDescription(const std::string& dev, const std::string& name)throw(NutException)
663 return get("CMDDESC", dev + " " + name)[0];
666 void TcpClient::executeDeviceCommand(const std::string& dev, const std::string& name)throw(NutException)
668 detectError(sendQuery("INSTCMD " + dev + " " + name));
671 void TcpClient::deviceLogin(const std::string& dev)throw(NutException)
673 detectError(sendQuery("LOGIN " + dev));
676 void TcpClient::deviceMaster(const std::string& dev)throw(NutException)
678 detectError(sendQuery("MASTER " + dev));
681 void TcpClient::deviceForcedShutdown(const std::string& dev)throw(NutException)
683 detectError(sendQuery("FSD " + dev));
686 int TcpClient::deviceGetNumLogins(const std::string& dev)throw(NutException)
688 std::string num = get("NUMLOGINS", dev)[0];
689 return atoi(num.c_str());
693 std::vector<std::string> TcpClient::get
694 (const std::string& subcmd, const std::string& params) throw(NutException)
696 std::string req = subcmd;
697 if(!params.empty())
699 req += " " + params;
701 std::string res = sendQuery("GET " + req);
702 detectError(res);
703 if(res.substr(0, req.size()) != req)
705 throw NutException("Invalid response");
708 return explode(res, req.size());
711 std::vector<std::vector<std::string> > TcpClient::list
712 (const std::string& subcmd, const std::string& params) throw(NutException)
714 std::string req = subcmd;
715 if(!params.empty())
717 req += " " + params;
719 std::string res = sendQuery("LIST " + req);
720 detectError(res);
721 if(res != ("BEGIN LIST " + req))
723 throw NutException("Invalid response");
726 std::vector<std::vector<std::string> > arr;
727 while(true)
729 res = _socket->read();
730 detectError(res);
731 if(res == ("END LIST " + req))
733 return arr;
735 if(res.substr(0, req.size()) == req)
737 arr.push_back(explode(res, req.size()));
739 else
741 throw NutException("Invalid response");
746 std::string TcpClient::sendQuery(const std::string& req)throw(IOException)
748 _socket->write(req);
749 return _socket->read();
752 void TcpClient::detectError(const std::string& req)throw(NutException)
754 if(req.substr(0,3)=="ERR")
756 throw NutException(req.substr(4));
760 std::vector<std::string> TcpClient::explode(const std::string& str, size_t begin)
762 std::vector<std::string> res;
763 std::string temp;
765 enum STATE {
766 INIT,
767 SIMPLE_STRING,
768 QUOTED_STRING,
769 SIMPLE_ESCAPE,
770 QUOTED_ESCAPE
771 } state = INIT;
773 for(size_t idx=begin; idx<str.size(); ++idx)
775 char c = str[idx];
776 switch(state)
778 case INIT:
779 if(c==' ' /* || c=='\t' */)
780 { /* Do nothing */ }
781 else if(c=='"')
783 state = QUOTED_STRING;
785 else if(c=='\\')
787 state = SIMPLE_ESCAPE;
789 /* What about bad characters ? */
790 else
792 temp += c;
793 state = SIMPLE_STRING;
795 break;
796 case SIMPLE_STRING:
797 if(c==' ' /* || c=='\t' */)
799 /* if(!temp.empty()) : Must not occur */
800 res.push_back(temp);
801 temp.clear();
802 state = INIT;
804 else if(c=='\\')
806 state = SIMPLE_ESCAPE;
808 else if(c=='"')
810 /* if(!temp.empty()) : Must not occur */
811 res.push_back(temp);
812 temp.clear();
813 state = QUOTED_STRING;
815 /* What about bad characters ? */
816 else
818 temp += c;
820 break;
821 case QUOTED_STRING:
822 if(c=='\\')
824 state = QUOTED_ESCAPE;
826 else if(c=='"')
828 res.push_back(temp);
829 temp.clear();
830 state = INIT;
832 /* What about bad characters ? */
833 else
835 temp += c;
837 break;
838 case SIMPLE_ESCAPE:
839 if(c=='\\' || c=='"' || c==' ' /* || c=='\t'*/)
841 temp += c;
843 else
845 temp += '\\' + c; // Really do this ?
847 state = SIMPLE_STRING;
848 break;
849 case QUOTED_ESCAPE:
850 if(c=='\\' || c=='"')
852 temp += c;
854 else
856 temp += '\\' + c; // Really do this ?
858 state = QUOTED_STRING;
859 break;
863 if(!temp.empty())
865 res.push_back(temp);
868 return res;
871 std::string TcpClient::escape(const std::string& str)
873 std::string res = "\"";
875 for(size_t n=0; n<str.size(); n++)
877 char c = str[n];
878 if(c=='"')
879 res += "\\\"";
880 else if(c=='\\')
881 res += "\\\\";
882 else
883 res += c;
886 res += '"';
887 return res;
892 * Device implementation
896 Device::Device(Client* client, const std::string& name):
897 _client(client),
898 _name(name)
902 Device::Device(const Device& dev):
903 _client(dev._client),
904 _name(dev._name)
908 Device::~Device()
912 std::string Device::getName()const
914 return _name;
917 const Client* Device::getClient()const
919 return _client;
922 Client* Device::getClient()
924 return _client;
927 bool Device::isOk()const
929 return _client!=NULL && !_name.empty();
932 Device::operator bool()const
934 return isOk();
937 bool Device::operator!()const
939 return !isOk();
942 bool Device::operator==(const Device& dev)const
944 return dev._client==_client && dev._name==_name;
947 bool Device::operator<(const Device& dev)const
949 return getName()<dev.getName();
952 std::string Device::getDescription()throw(NutException)
954 return getClient()->getDeviceDescription(getName());
957 std::vector<std::string> Device::getVariableValue(const std::string& name)
958 throw(NutException)
960 return getClient()->getDeviceVariableValue(getName(), name);
963 std::map<std::string,std::vector<std::string> > Device::getVariableValues()
964 throw(NutException)
966 return getClient()->getDeviceVariableValues(getName());
969 std::set<std::string> Device::getVariableNames()throw(NutException)
971 return getClient()->getDeviceVariableNames(getName());
974 std::set<std::string> Device::getRWVariableNames()throw(NutException)
976 return getClient()->getDeviceRWVariableNames(getName());
979 void Device::setVariable(const std::string& name, const std::string& value)throw(NutException)
981 getClient()->setDeviceVariable(getName(), name, value);
984 void Device::setVariable(const std::string& name, const std::vector<std::string>& values)
985 throw(NutException)
987 getClient()->setDeviceVariable(getName(), name, values);
992 Variable Device::getVariable(const std::string& name)throw(NutException)
994 if(getClient()->hasDeviceVariable(getName(), name))
995 return Variable(this, name);
996 else
997 return Variable(NULL, "");
1000 std::set<Variable> Device::getVariables()throw(NutException)
1002 std::set<Variable> set;
1004 std::set<std::string> names = getClient()->getDeviceVariableNames(getName());
1005 for(std::set<std::string>::iterator it=names.begin(); it!=names.end(); ++it)
1007 set.insert(Variable(this, *it));
1010 return set;
1013 std::set<Variable> Device::getRWVariables()throw(NutException)
1015 std::set<Variable> set;
1017 std::set<std::string> names = getClient()->getDeviceRWVariableNames(getName());
1018 for(std::set<std::string>::iterator it=names.begin(); it!=names.end(); ++it)
1020 set.insert(Variable(this, *it));
1023 return set;
1026 std::set<std::string> Device::getCommandNames()throw(NutException)
1028 return getClient()->getDeviceCommandNames(getName());
1031 std::set<Command> Device::getCommands()throw(NutException)
1033 std::set<Command> cmds;
1035 std::set<std::string> res = getCommandNames();
1036 for(std::set<std::string>::iterator it=res.begin(); it!=res.end(); ++it)
1038 cmds.insert(Command(this, *it));
1041 return cmds;
1044 Command Device::getCommand(const std::string& name)throw(NutException)
1046 if(getClient()->hasDeviceCommand(getName(), name))
1047 return Command(this, name);
1048 else
1049 return Command(NULL, "");
1052 void Device::executeCommand(const std::string& name)throw(NutException)
1054 getClient()->executeDeviceCommand(getName(), name);
1057 void Device::login()throw(NutException)
1059 getClient()->deviceLogin(getName());
1062 void Device::master()throw(NutException)
1064 getClient()->deviceMaster(getName());
1067 void Device::forcedShutdown()throw(NutException)
1071 int Device::getNumLogins()throw(NutException)
1073 return getClient()->deviceGetNumLogins(getName());
1078 * Variable implementation
1082 Variable::Variable(Device* dev, const std::string& name):
1083 _device(dev),
1084 _name(name)
1088 Variable::Variable(const Variable& var):
1089 _device(var._device),
1090 _name(var._name)
1094 Variable::~Variable()
1098 std::string Variable::getName()const
1100 return _name;
1103 const Device* Variable::getDevice()const
1105 return _device;
1108 Device* Variable::getDevice()
1110 return _device;
1113 bool Variable::isOk()const
1115 return _device!=NULL && !_name.empty();
1119 Variable::operator bool()const
1121 return isOk();
1124 bool Variable::operator!()const
1126 return !isOk();
1129 bool Variable::operator==(const Variable& var)const
1131 return var._device==_device && var._name==_name;
1134 bool Variable::operator<(const Variable& var)const
1136 return getName()<var.getName();
1139 std::vector<std::string> Variable::getValue()throw(NutException)
1141 return getDevice()->getClient()->getDeviceVariableValue(getDevice()->getName(), getName());
1144 std::string Variable::getDescription()throw(NutException)
1146 return getDevice()->getClient()->getDeviceVariableDescription(getDevice()->getName(), getName());
1149 void Variable::setValue(const std::string& value)throw(NutException)
1151 getDevice()->setVariable(getName(), value);
1154 void Variable::setValues(const std::vector<std::string>& values)throw(NutException)
1156 getDevice()->setVariable(getName(), values);
1162 * Command implementation
1166 Command::Command(Device* dev, const std::string& name):
1167 _device(dev),
1168 _name(name)
1172 Command::Command(const Command& cmd):
1173 _device(cmd._device),
1174 _name(cmd._name)
1178 Command::~Command()
1182 std::string Command::getName()const
1184 return _name;
1187 const Device* Command::getDevice()const
1189 return _device;
1192 Device* Command::getDevice()
1194 return _device;
1197 bool Command::isOk()const
1199 return _device!=NULL && !_name.empty();
1203 Command::operator bool()const
1205 return isOk();
1208 bool Command::operator!()const
1210 return !isOk();
1213 bool Command::operator==(const Command& cmd)const
1215 return cmd._device==_device && cmd._name==_name;
1218 bool Command::operator<(const Command& cmd)const
1220 return getName()<cmd.getName();
1223 std::string Command::getDescription()throw(NutException)
1225 return getDevice()->getClient()->getDeviceCommandDescription(getDevice()->getName(), getName());
1228 void Command::execute()throw(NutException)
1230 getDevice()->executeCommand(getName());
1233 } /* namespace nut */
1237 * C nutclient API.
1239 extern "C" {
1242 strarr strarr_alloc(unsigned short count)
1244 strarr arr = (strarr)xcalloc(count+1, sizeof(char*));
1245 arr[count] = NULL;
1246 return arr;
1249 void strarr_free(strarr arr)
1251 char** pstr = arr;
1252 while(*pstr!=NULL)
1254 free(*pstr);
1255 ++pstr;
1257 free(arr);
1261 static strarr stringset_to_strarr(const std::set<std::string>& strset)
1263 strarr arr = strarr_alloc(strset.size());
1264 strarr pstr = arr;
1265 for(std::set<std::string>::const_iterator it=strset.begin(); it!=strset.end(); ++it)
1267 *pstr = xstrdup(it->c_str());
1269 return arr;
1272 static strarr stringvector_to_strarr(const std::vector<std::string>& strset)
1274 strarr arr = strarr_alloc(strset.size());
1275 strarr pstr = arr;
1276 for(std::vector<std::string>::const_iterator it=strset.begin(); it!=strset.end(); ++it)
1278 *pstr = xstrdup(it->c_str());
1280 return arr;
1284 NUTCLIENT_TCP_t nutclient_tcp_create_client(const char* host, unsigned short port)
1286 nut::TcpClient* client = new nut::TcpClient;
1289 client->connect(host, port);
1290 return (NUTCLIENT_TCP_t)client;
1292 catch(nut::NutException& ex)
1294 // TODO really catch it
1295 delete client;
1296 return NULL;
1301 void nutclient_destroy(NUTCLIENT_t client)
1303 if(client)
1305 delete (nut::Client*)client;
1309 int nutclient_tcp_is_connected(NUTCLIENT_TCP_t client)
1311 if(client)
1313 nut::TcpClient* cl = dynamic_cast<nut::TcpClient*>((nut::Client*)client);
1314 if(cl)
1316 return cl->isConnected() ? 1 : 0;
1319 return 0;
1322 void nutclient_tcp_disconnect(NUTCLIENT_TCP_t client)
1324 if(client)
1326 nut::TcpClient* cl = dynamic_cast<nut::TcpClient*>((nut::Client*)client);
1327 if(cl)
1329 cl->disconnect();
1335 int nutclient_tcp_reconnect(NUTCLIENT_TCP_t client)
1337 if(client)
1339 nut::TcpClient* cl = dynamic_cast<nut::TcpClient*>((nut::Client*)client);
1340 if(cl)
1344 cl->connect();
1345 return 0;
1347 catch(...){}
1350 return -1;
1353 void nutclient_tcp_set_timeout(NUTCLIENT_TCP_t client, long timeout)
1355 if(client)
1357 nut::TcpClient* cl = dynamic_cast<nut::TcpClient*>((nut::Client*)client);
1358 if(cl)
1360 cl->setTimeout(timeout);
1365 long nutclient_tcp_get_timeout(NUTCLIENT_TCP_t client)
1367 if(client)
1369 nut::TcpClient* cl = dynamic_cast<nut::TcpClient*>((nut::Client*)client);
1370 if(cl)
1372 return cl->getTimeout();
1375 return -1;
1379 void nutclient_authenticate(NUTCLIENT_t client, const char* login, const char* passwd)
1381 if(client)
1383 nut::Client* cl = (nut::Client*)client;
1384 if(cl)
1388 cl->authenticate(login, passwd);
1390 catch(...){}
1395 void nutclient_logout(NUTCLIENT_t client)
1397 if(client)
1399 nut::Client* cl = (nut::Client*)client;
1400 if(cl)
1404 cl->logout();
1406 catch(...){}
1411 void nutclient_device_login(NUTCLIENT_t client, const char* dev)
1413 if(client)
1415 nut::Client* cl = (nut::Client*)client;
1416 if(cl)
1420 cl->deviceLogin(dev);
1422 catch(...){}
1427 int nutclient_get_device_num_logins(NUTCLIENT_t client, const char* dev)
1429 if(client)
1431 nut::Client* cl = (nut::Client*)client;
1432 if(cl)
1436 return cl->deviceGetNumLogins(dev);
1438 catch(...){}
1441 return -1;
1445 void nutclient_device_master(NUTCLIENT_t client, const char* dev)
1447 if(client)
1449 nut::Client* cl = (nut::Client*)client;
1450 if(cl)
1454 cl->deviceMaster(dev);
1456 catch(...){}
1461 void nutclient_device_forced_shutdown(NUTCLIENT_t client, const char* dev)
1463 if(client)
1465 nut::Client* cl = (nut::Client*)client;
1466 if(cl)
1470 cl->deviceForcedShutdown(dev);
1472 catch(...){}
1477 strarr nutclient_get_devices(NUTCLIENT_t client)
1479 if(client)
1481 nut::Client* cl = (nut::Client*)client;
1482 if(cl)
1486 return stringset_to_strarr(cl->getDeviceNames());
1488 catch(...){}
1491 return NULL;
1494 int nutclient_has_device(NUTCLIENT_t client, const char* dev)
1496 if(client)
1498 nut::Client* cl = (nut::Client*)client;
1499 if(cl)
1503 return cl->hasDevice(dev)?1:0;
1505 catch(...){}
1508 return 0;
1511 char* nutclient_get_device_description(NUTCLIENT_t client, const char* dev)
1513 if(client)
1515 nut::Client* cl = (nut::Client*)client;
1516 if(cl)
1520 return xstrdup(cl->getDeviceDescription(dev).c_str());
1522 catch(...){}
1525 return NULL;
1528 strarr nutclient_get_device_variables(NUTCLIENT_t client, const char* dev)
1530 if(client)
1532 nut::Client* cl = (nut::Client*)client;
1533 if(cl)
1537 return stringset_to_strarr(cl->getDeviceVariableNames(dev));
1539 catch(...){}
1542 return NULL;
1545 strarr nutclient_get_device_rw_variables(NUTCLIENT_t client, const char* dev)
1547 if(client)
1549 nut::Client* cl = (nut::Client*)client;
1550 if(cl)
1554 return stringset_to_strarr(cl->getDeviceRWVariableNames(dev));
1556 catch(...){}
1559 return NULL;
1562 int nutclient_has_device_variable(NUTCLIENT_t client, const char* dev, const char* var)
1564 if(client)
1566 nut::Client* cl = (nut::Client*)client;
1567 if(cl)
1571 return cl->hasDeviceVariable(dev, var)?1:0;
1573 catch(...){}
1576 return 0;
1579 char* nutclient_get_device_variable_description(NUTCLIENT_t client, const char* dev, const char* var)
1581 if(client)
1583 nut::Client* cl = (nut::Client*)client;
1584 if(cl)
1588 return xstrdup(cl->getDeviceVariableDescription(dev, var).c_str());
1590 catch(...){}
1593 return NULL;
1596 strarr nutclient_get_device_variable_values(NUTCLIENT_t client, const char* dev, const char* var)
1598 if(client)
1600 nut::Client* cl = (nut::Client*)client;
1601 if(cl)
1605 return stringvector_to_strarr(cl->getDeviceVariableValue(dev, var));
1607 catch(...){}
1610 return NULL;
1613 void nutclient_set_device_variable_value(NUTCLIENT_t client, const char* dev, const char* var, const char* value)
1615 if(client)
1617 nut::Client* cl = (nut::Client*)client;
1618 if(cl)
1622 cl->setDeviceVariable(dev, var, value);
1624 catch(...){}
1629 void nutclient_set_device_variable_values(NUTCLIENT_t client, const char* dev, const char* var, const strarr values)
1631 if(client)
1633 nut::Client* cl = (nut::Client*)client;
1634 if(cl)
1638 std::vector<std::string> vals;
1639 strarr pstr = (strarr)values;
1640 while(*pstr)
1642 vals.push_back(std::string(*pstr));
1643 ++pstr;
1646 cl->setDeviceVariable(dev, var, vals);
1648 catch(...){}
1655 strarr nutclient_get_device_commands(NUTCLIENT_t client, const char* dev)
1657 if(client)
1659 nut::Client* cl = (nut::Client*)client;
1660 if(cl)
1664 return stringset_to_strarr(cl->getDeviceCommandNames(dev));
1666 catch(...){}
1669 return NULL;
1673 int nutclient_has_device_command(NUTCLIENT_t client, const char* dev, const char* cmd)
1675 if(client)
1677 nut::Client* cl = (nut::Client*)client;
1678 if(cl)
1682 return cl->hasDeviceCommand(dev, cmd)?1:0;
1684 catch(...){}
1687 return 0;
1691 char* nutclient_get_device_command_description(NUTCLIENT_t client, const char* dev, const char* cmd)
1693 if(client)
1695 nut::Client* cl = (nut::Client*)client;
1696 if(cl)
1700 return xstrdup(cl->getDeviceCommandDescription(dev, cmd).c_str());
1702 catch(...){}
1705 return NULL;
1708 void nutclient_execute_device_command(NUTCLIENT_t client, const char* dev, const char* cmd)
1710 if(client)
1712 nut::Client* cl = (nut::Client*)client;
1713 if(cl)
1717 cl->executeDeviceCommand(dev, cmd);
1719 catch(...){}
1724 } /* extern "C" */