Instrument Neutral Distributed Interface INDI 2.2.5
RemoteDvrInfo.cpp
Go to the documentation of this file.
1/* INDI Server for protocol version 1.7.
2 * Copyright (C) 2007 Elwood C. Downey <[email protected]>
3 2013 Jasem Mutlaq <[email protected]>
4 2022 Ludovic Pollet
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library 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 GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18*/
19#include "RemoteDvrInfo.hpp"
20#include "Utils.hpp"
21#include "Constants.hpp"
22#include "Msg.hpp"
23#include "CommandLineArgs.hpp"
24
25#include <cstdio>
26#include <sys/socket.h>
27#include <netinet/in.h>
28#include <netdb.h>
29
30using namespace indiserver::constants;
31
32void RemoteDvrInfo::extractRemoteId(const std::string &name, std::string &o_host, int &o_port, std::string &o_dev) const
33{
34 char dev[MAXINDIDEVICE] = {0};
35 char host[maxStringBufferLength] = {0};
36
37 /* extract host and port from name*/
38 int indi_port = indiPortDefault;
39 if (sscanf(name.c_str(), "%[^@]@%[^:]:%d", dev, host, &indi_port) < 2)
40 {
41 // Device missing? Try a different syntax for all devices
42 if (sscanf(name.c_str(), "@%[^:]:%d", host, &indi_port) < 1)
43 {
44 log(fmt("Bad remote device syntax: %s\n", name.c_str()));
45 Bye();
46 }
47 }
48
49 o_host = host;
50 o_port = indi_port;
51 o_dev = dev;
52}
53
54/* start the given remote INDI driver connection.
55 * exit if trouble.
56 */
58{
59 int sockfd;
60 std::string dev;
61 extractRemoteId(name, host, port, dev);
62
63 /* connect */
64 sockfd = openINDIServer();
65
66 /* record flag pid, io channels, init lp and snoop list */
67
68 this->setFds(sockfd, sockfd);
69
71 log(fmt("socket=%d\n", sockfd));
72
73 /* N.B. storing name now is key to limiting outbound traffic to this
74 * dev.
75 */
76 if (!dev.empty())
77 this->dev.insert(dev);
78
79 /* Sending getProperties with device lets remote server limit its
80 * outbound (and our inbound) traffic on this socket to this device.
81 */
82 XMLEle *root = addXMLEle(NULL, "getProperties");
83
84 if (!dev.empty())
85 {
86 addXMLAtt(root, "device", dev.c_str());
87 addXMLAtt(root, "version", TO_STRING(INDIV));
88 }
89 else
90 {
91 // This informs downstream server that it is connecting to an upstream server
92 // and not a regular client. The difference is in how it treats snooping properties
93 // among properties.
94 addXMLAtt(root, "device", "*");
95 addXMLAtt(root, "version", TO_STRING(INDIV));
96 }
97
98 Msg *mp = new Msg(nullptr, root);
99
100 // pushmsg can kill this. do at end
101 pushMsg(mp);
102}
103
104int RemoteDvrInfo::openINDIServer()
105{
106 struct sockaddr_in serv_addr;
107 struct hostent *hp;
108 int sockfd;
109
110 /* lookup host address */
111 hp = gethostbyname(host.c_str());
112 if (!hp)
113 {
114 log(fmt("gethostbyname(%s): %s\n", host.c_str(), strerror(errno)));
115 Bye();
116 }
117
118 /* create a socket to the INDI server */
119 (void)memset((char *)&serv_addr, 0, sizeof(serv_addr));
120 serv_addr.sin_family = AF_INET;
121 serv_addr.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr_list[0]))->s_addr;
122 serv_addr.sin_port = htons(port);
123 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
124 {
125 log(fmt("socket(%s,%d): %s\n", host.c_str(), port, strerror(errno)));
126 Bye();
127 }
128
129 /* connect */
130 if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
131 {
132 log(fmt("connect(%s,%d): %s\n", host.c_str(), port, strerror(errno)));
133 Bye();
134 }
135
136 /* ok */
137 return (sockfd);
138}
139
142
144 DvrInfo(model),
145 host(model.host),
146 port(model.port)
147{}
148
151
153{
154 return new RemoteDvrInfo(*this);
155}
CommandLineArgs * userConfigurableArguments
std::string fmt(const char *fmt,...)
Definition Utils.cpp:241
void Bye()
Definition Utils.cpp:108
#define TO_STRING(x)
Definition Utils.hpp:46
std::set< std::string > dev
Definition DvrInfo.hpp:59
void log(const std::string &log) const override
Definition DvrInfo.cpp:320
std::string name
Definition DvrInfo.hpp:57
void pushMsg(Msg *msg)
Definition MsgQueue.cpp:336
void setFds(int rFd, int wFd)
Definition MsgQueue.cpp:284
Definition Msg.hpp:33
void start() override
RemoteDvrInfo * clone() const override
virtual ~RemoteDvrInfo()
std::string host
int errno
#define MAXINDIDEVICE
Definition indiapi.h:191
#define INDIV
Definition indiapi.h:134
XMLEle * addXMLEle(XMLEle *parent, const char *tag)
add an element with the given tag to the given element. parent can be NULL to make a new root.
Definition lilxml.cpp:670
XMLAtt * addXMLAtt(XMLEle *ep, const char *name, const char *valu)
Add an XML attribute to an existing XML element.
Definition lilxml.cpp:706
constexpr unsigned maxStringBufferLength
Definition Constants.hpp:24
constexpr unsigned indiPortDefault
Definition Constants.hpp:23