source: BAORadio/libindi/libindi/Indi_Stellarium/src/Connection.cpp @ 623

Last change on this file since 623 was 623, checked in by frichard, 13 years ago
File size: 9.8 KB
Line 
1/*
2The stellarium telescope library helps building
3telescope server programs, that can communicate with stellarium
4by means of the stellarium TCP telescope protocol.
5It also contains smaple server classes (dummy, Meade LX200).
6
7Author and Copyright of this file and of the stellarium telescope library:
8Johannes Gajdosik, 2006
9
10This library is free software; you can redistribute it and/or
11modify it under the terms of the GNU Lesser General Public
12License as published by the Free Software Foundation; either
13version 2.1 of the License, or (at your option) any later version.
14
15This library is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18Lesser General Public License for more details.
19
20You should have received a copy of the GNU Lesser General Public
21License along with this library; if not, write to the Free Software
22Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23*/
24
25#include "Connection.hpp"
26#include "Server.hpp"
27#include "LogFile.hpp"
28
29#include <iostream>
30#include <iomanip>
31using namespace std;
32
33#include <math.h>
34
35#ifdef DEBUG5
36struct PrintRaDec
37{
38        PrintRaDec(const unsigned int ra_int, const int dec_int) : ra_int(ra_int), dec_int(dec_int) {}
39        const unsigned int ra_int;
40        const int dec_int;
41};
42
43static ostream &operator<<(ostream &o,const PrintRaDec &x)
44{
45        unsigned int h = x.ra_int;
46        int d = (int)floor(0.5+x.dec_int*(360*3600*1000/4294967296.0));
47        char dec_sign;
48        if (d >= 0)
49        {
50                if (d > 90*3600*1000)
51                {
52                        d =  180*3600*1000 - d;
53                        h += 0x80000000;
54                }
55                dec_sign = '+';
56        }
57        else
58        {
59                if (d < -90*3600*1000)
60                {
61                        d = -180*3600*1000 - d;
62                        h += 0x80000000;
63                }
64                d = -d;
65                dec_sign = '-';
66        }
67        h = (unsigned int)floor(0.5+h*(24*3600*10000/4294967296.0));
68        const int ra_ms = h % 10000; h /= 10000;
69        const int ra_s = h % 60; h /= 60;
70        const int ra_m = h % 60; h /= 60;
71        h %= 24;
72        const int dec_ms = d % 1000; d /= 1000;
73        const int dec_s = d % 60; d /= 60;
74        const int dec_m = d % 60; d /= 60;
75        o << "ra = "
76          << setfill(' ') << setw(2) << h << 'h'
77          << setfill('0') << setw(2) << ra_m << 'm'
78          << setfill('0') << setw(2) << ra_s << '.'
79          << setfill('0') << setw(4) << ra_ms
80          << " dec = "
81          << ((d<10)?" ":"") << dec_sign << d << 'd'
82          << setfill('0') << setw(2) << dec_m << 'm'
83          << setfill('0') << setw(2) << dec_s << '.'
84          << setfill('0') << setw(3) << dec_ms
85          << setfill(' ');
86        return o;
87}
88#endif
89
90Connection::Connection(Server &server, SOCKET fd) : Socket(server, fd)
91{
92        read_buff_end = read_buff;
93        write_buff_end = write_buff;
94        server_minus_client_time = 0x7FFFFFFFFFFFFFFFLL;
95}
96
97void Connection::prepareSelectFds(fd_set &read_fds,
98                                  fd_set &write_fds,
99                                  int &fd_max)
100{
101        if (!IS_INVALID_SOCKET(fd))
102        {
103                if (fd_max < (int)fd)
104                        fd_max = (int)fd;
105                if (write_buff_end > write_buff)
106                        FD_SET(fd, &write_fds);
107                FD_SET(fd, &read_fds);
108        }
109}
110
111void Connection::handleSelectFds(const fd_set &read_fds,
112                                 const fd_set &write_fds)
113{
114        if (!IS_INVALID_SOCKET(fd))
115        {
116                if (FD_ISSET(fd, const_cast<fd_set *>(&write_fds)))
117                {
118                        performWriting();
119                }
120                if (!IS_INVALID_SOCKET(fd) && FD_ISSET(fd, const_cast<fd_set *>(&read_fds)))
121                {
122                        performReading();
123                }
124        }
125}
126
127
128void Connection::performWriting(void)
129{
130        const int to_write = write_buff_end - write_buff;
131        const int rc = writeNonblocking(write_buff, to_write);
132        if (rc < 0)
133        {
134                if (ERRNO != EINTR && ERRNO != EAGAIN)
135                {
136                        *log_file << Now() << "Connection::performWriting: writeNonblocking failed: "
137                                           << STRERROR(ERRNO) << endl;
138                hangup();
139                }
140        }
141        else if (rc > 0)
142        {
143        #ifdef DEBUG5
144                if (isAsciiConnection())
145                {
146                        *log_file << Now() << "Connection::performWriting: writeNonblocking("
147                                           << to_write << ") returned "
148                                           << rc << "; ";
149                        for (int i = 0; i < rc; i++)
150                                *log_file << write_buff[i];
151                        *log_file << endl;
152                }
153        #endif
154                if (rc >= to_write)
155                {
156                        // everything written
157                        write_buff_end = write_buff;
158                }
159                else
160                {
161                        // partly written
162                        memmove(write_buff, write_buff + rc, to_write - rc);
163                        write_buff_end -= rc;
164                }
165        }
166}
167
168void Connection::performReading(void)
169{
170        const int to_read = read_buff + sizeof(read_buff) - read_buff_end;
171        const int rc = readNonblocking(read_buff_end, to_read);
172        if (rc < 0)
173        {
174                if (ERRNO == ECONNRESET)
175                {
176                        *log_file << Now() << "Connection::performReading: "
177                                              "client has closed the connection" << endl;
178                        hangup();
179                } 
180                else if (ERRNO != EINTR && ERRNO != EAGAIN)
181                {
182                        *log_file << Now() << "Connection::performReading: readNonblocking failed: "
183                                           << STRERROR(ERRNO) << endl;
184                        hangup();
185                }
186        } 
187        else if (rc == 0)
188        {
189                if (isTcpConnection())
190                {
191                        *log_file << Now() << "Connection::performReading: "
192                                              "client has closed the connection" << endl;
193                        hangup();
194                }
195        }
196        else
197        {
198        #ifdef DEBUG5
199                if (isAsciiConnection())
200                {
201                        *log_file << Now() << "Connection::performReading: readNonblocking returned "
202                                           << rc << "; ";
203                        for (int i = 0; i < rc; i++)
204                                *log_file << read_buff_end[i];
205                        *log_file << endl;
206                }
207        #endif
208       
209                read_buff_end += rc;
210                const char *p = read_buff;
211                dataReceived(p, read_buff_end);
212                if (p >= read_buff_end)
213                {
214                        // everything handled
215                        //*log_file << Now() << "Connection::performReading: everything handled" << endl;
216                        read_buff_end = read_buff;
217                }
218                else if (p > read_buff)
219                {
220                        //*log_file << Now() << "Connection::performReading: partly handled: "
221                        //          << (p-read_buff) << endl;
222                        // partly handled
223                        memmove(read_buff, p, read_buff_end - p);
224                        read_buff_end -= (p - read_buff);
225                }
226        }
227}
228
229void Connection::dataReceived(const char *&p, const char *read_buff_end)
230{
231        while (read_buff_end - p >= 2)
232        {
233                const int size = (int)( ((unsigned char)(p[0])) |
234                                        (((unsigned int)(unsigned char)(p[1])) << 8) );
235                if (size > (int)sizeof(read_buff) || size < 4)
236                {
237                        *log_file << Now() << "Connection::dataReceived: "
238                                              "bad packet size: " << size << endl;
239                        hangup();
240                        return;
241                }
242                if (size > read_buff_end-p)
243                {
244                        // wait for complete packet
245                        break;
246                }
247                const int type = (int)( ((unsigned char)(p[2])) |
248                                        (((unsigned int)(unsigned char)(p[3])) << 8) );
249                // dispatch:
250                switch (type)
251                {
252                        case 0:
253                        //A "go to" command
254                        {
255                                if (size < 12)
256                                {
257                                        *log_file << Now() << "Connection::dataReceived: "
258                                                              "type 0: bad packet size: " << size << endl;
259                                        hangup();
260                                        return;
261                                }
262                                const long long int client_micros = (long long int)
263                                               (  ((unsigned long long int)(unsigned char)(p[ 4])) |
264                                                 (((unsigned long long int)(unsigned char)(p[ 5])) <<  8) |
265                                                 (((unsigned long long int)(unsigned char)(p[ 6])) << 16) |
266                                                 (((unsigned long long int)(unsigned char)(p[ 7])) << 24) |
267                                                 (((unsigned long long int)(unsigned char)(p[ 8])) << 32) |
268                                                 (((unsigned long long int)(unsigned char)(p[ 9])) << 40) |
269                                                 (((unsigned long long int)(unsigned char)(p[10])) << 48) |
270                                                 (((unsigned long long int)(unsigned char)(p[11])) << 56) );
271                                server_minus_client_time = GetNow() - client_micros;
272                                const unsigned int ra_int =
273                                                  ((unsigned int)(unsigned char)(p[12])) |
274                                                 (((unsigned int)(unsigned char)(p[13])) <<  8) |
275                                                 (((unsigned int)(unsigned char)(p[14])) << 16) |
276                                                 (((unsigned int)(unsigned char)(p[15])) << 24);
277                                const int dec_int =
278                                          (int)(  ((unsigned int)(unsigned char)(p[16])) |
279                                                 (((unsigned int)(unsigned char)(p[17])) <<  8) |
280                                                 (((unsigned int)(unsigned char)(p[18])) << 16) |
281                                                 (((unsigned int)(unsigned char)(p[19])) << 24) );
282                                #ifdef DEBUG5
283                                *log_file << Now() << "Connection::dataReceived: "
284                                                   << PrintRaDec(ra_int,dec_int)
285                                                   << endl;
286                                #endif
287                               
288                                server.gotoReceived(ra_int, dec_int);
289                        }
290                        break;
291                       
292                        default:
293                        //No other types of commands are acceptable at the moment
294                                *log_file << Now()
295                                          << "Connection::dataReceived: "
296                                             "ignoring unknown packet, type: "
297                                          << type
298                                          << endl;
299                        break;
300                }
301               
302                p += size;
303        }
304}
305
306void Connection::sendPosition(unsigned int ra_int, int dec_int, int status)
307{
308        if (!IS_INVALID_SOCKET(fd))
309        {
310        #ifdef DEBUG5
311                *log_file << Now() << "Connection::sendPosition: "
312                                   << PrintRaDec(ra_int, dec_int)
313                                   << endl;
314        #endif
315        if (write_buff_end - write_buff + 24 < (int)sizeof(write_buff))
316        {
317                // length of packet:
318                *write_buff_end++ = 24;
319                *write_buff_end++ = 0;
320                // type of packet:
321                *write_buff_end++ = 0;
322                *write_buff_end++ = 0;
323                // server_micros:
324                long long int now = GetNow();
325                *write_buff_end++ = now; now>>=8;
326                *write_buff_end++ = now; now>>=8;
327                *write_buff_end++ = now; now>>=8;
328                *write_buff_end++ = now; now>>=8;
329                *write_buff_end++ = now; now>>=8;
330                *write_buff_end++ = now; now>>=8;
331                *write_buff_end++ = now; now>>=8;
332                *write_buff_end++ = now;
333                // ra:
334                *write_buff_end++ = ra_int; ra_int>>=8;
335                *write_buff_end++ = ra_int; ra_int>>=8;
336                *write_buff_end++ = ra_int; ra_int>>=8;
337                *write_buff_end++ = ra_int;
338                // dec:
339                *write_buff_end++ = dec_int; dec_int>>=8;
340                *write_buff_end++ = dec_int; dec_int>>=8;
341                *write_buff_end++ = dec_int; dec_int>>=8;
342                *write_buff_end++ = dec_int;
343                // status:
344                *write_buff_end++ = status; status>>=8;
345                *write_buff_end++ = status; status>>=8;
346                *write_buff_end++ = status; status>>=8;
347                *write_buff_end++ = status;
348                }
349                else
350                {
351                        *log_file << Now() << "Connection::sendPosition: "
352                                              "communication is too slow, I will ignore this command"
353                                           << endl;
354                }
355        }
356}
357
Note: See TracBrowser for help on using the repository browser.