1 /*
2  # This file is part of the Astrometry.net suite.
3  # Licensed under a 3-clause BSD style license - see LICENSE
4  */
5 
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <errno.h>
10 #include <string.h>
11 #include <sys/types.h>
12 
13 #ifdef _WIN32 //# Modified by Robert Lancaster for the StellarSolver Internal Library
14 #include <winsock2.h>
15 #include <string.h>
16 #else
17 #include <sys/socket.h>
18 #include <netinet/in.h>
19 #include <arpa/inet.h>
20 #include <netdb.h>
21 #endif
22 
23 #include <assert.h>
24 
25 #include "solvedclient.h"
26 #include "bl.h"
27 
28 static int serveraddr_initialized = 0;
29 static struct sockaddr_in serveraddr;
30 static FILE* fserver = NULL;
31 
solvedclient_set_server(char * addr)32 int solvedclient_set_server(char* addr) {
33     char buf[256];
34     char* ind;
35     struct hostent* he;
36     int len;
37     int port;
38     if (fserver) {
39         if (fflush(fserver) ||
40             fclose(fserver)) {
41             fprintf(stderr, "Failed to close previous connection to server.\n");
42         }
43         fserver = NULL;
44     }
45     if (!addr)
46         return -1;
47 #ifdef _WIN32 //# Modified by Robert Lancaster for the StellarSolver Internal Library
48     ind = strstr(addr, ":");
49 #else
50     ind = index(addr, ':');
51 #endif
52     if (!ind) {
53         fprintf(stderr, "Invalid IP:port address: %s\n", addr);
54         return -1;
55     }
56     len = ind - addr;
57     memcpy(buf, addr, len);
58     buf[len] = '\0';
59     he = gethostbyname(buf);
60     if (!he) {
61 #ifdef _WIN32 //# Modified by Robert Lancaster for the StellarSolver Internal Library
62         fprintf(stderr, "Solved server \"%s\" not found.\n", buf);
63 #else
64         fprintf(stderr, "Solved server \"%s\" not found: %s.\n", buf, hstrerror(h_errno));
65 #endif
66         return -1;
67     }
68     if (!serveraddr_initialized) {
69         memset(&serveraddr, 0, sizeof(serveraddr));
70         serveraddr_initialized = 1;
71     }
72     memcpy(&(serveraddr.sin_addr), he->h_addr, he->h_length);
73     port = atoi(ind+1);
74     serveraddr.sin_family = AF_INET;
75     serveraddr.sin_port = htons(port);
76 
77     return 0;
78 }
79 
connect_to_server()80 static int connect_to_server() {
81     int sock;
82     if (fserver)
83         return 0;
84     sock = socket(PF_INET, SOCK_STREAM, 0);
85     if (sock == -1) {
86         fprintf(stderr, "Couldn't create socket: %s\n", strerror(errno));
87         return -1;
88     }
89     fserver = fdopen(sock, "r+b");
90     if (!fserver) {
91         fprintf(stderr, "Failed to fdopen socket: %s\n", strerror(errno));
92         return -1;
93     }
94     assert(serveraddr_initialized);
95     // gcc with strict-aliasing warns about this cast but it should be okay.
96     if (connect(sock, (struct sockaddr*)&serveraddr, sizeof(serveraddr))) {
97         fprintf(stderr, "Couldn't connect to server: %s\n", strerror(errno));
98         if (fclose(fserver))
99             fprintf(stderr, "Failed to close socket: %s\n", strerror(errno));
100         fserver = NULL;
101         return -1;
102     }
103     return 0;
104 }
105 
solvedclient_get(int filenum,int fieldnum)106 int solvedclient_get(int filenum, int fieldnum) {
107     char buf[256];
108     const char* solvedstr = "solved";
109     int nchars;
110     int solved;
111 
112     if (connect_to_server())
113         return -1;
114     nchars = sprintf(buf, "get %i %i\n", filenum, fieldnum);
115     if ((fwrite(buf, 1, nchars, fserver) != nchars) ||
116         fflush(fserver)) {
117         fprintf(stderr, "Failed to write request to server: %s\n", strerror(errno));
118         fclose(fserver);
119         fserver = NULL;
120         return -1;
121     }
122     if (!fgets(buf, 256, fserver)) {
123         fprintf(stderr, "Couldn't read response: %s\n", strerror(errno));
124         fclose(fserver);
125         fserver = NULL;
126         return -1;
127     }
128     solved = (strncmp(buf, solvedstr, strlen(solvedstr)) == 0);
129     return solved;
130 }
131 
solvedclient_set(int filenum,int fieldnum)132 void solvedclient_set(int filenum, int fieldnum) {
133     char buf[256];
134     int nchars;
135     if (connect_to_server())
136         return;
137     nchars = sprintf(buf, "set %i %i\n", filenum, fieldnum);
138     if ((fwrite(buf, 1, nchars, fserver) != nchars) ||
139         fflush(fserver)) {
140         fprintf(stderr, "Failed to send command (%s) to solvedserver: %s\n", buf, strerror(errno));
141         return;
142     }
143     // wait for response.
144     if (!fgets(buf, 256, fserver)) {
145         fprintf(stderr, "Couldn't read response: %s\n", strerror(errno));
146         fclose(fserver);
147         fserver = NULL;
148         return;
149     }
150 }
151 
solvedclient_get_fields(int filenum,int firstfield,int lastfield,int maxnfields)152 il* solvedclient_get_fields(int filenum, int firstfield, int lastfield,
153                             int maxnfields) {
154     char* buf;
155     int bufsize;
156     il* list;
157     char* cptr;
158     int fld;
159     int nchars;
160 
161     if (connect_to_server())
162         return NULL;
163     bufsize = 100 + 10 * (maxnfields ? maxnfields : (1 + lastfield - firstfield));
164     buf = malloc(bufsize);
165     nchars = sprintf(buf, "getall %i %i %i %i\n", filenum, firstfield,
166                      lastfield, maxnfields);
167     if ((fwrite(buf, 1, nchars, fserver) != nchars) ||
168         fflush(fserver)) {
169         fprintf(stderr, "Failed to send command (%s) to solvedserver: %s\n", buf, strerror(errno));
170         return NULL;
171     }
172     // wait for response.
173     if (!fgets(buf, bufsize, fserver)) {
174         fprintf(stderr, "Couldn't read response: %s\n", strerror(errno));
175         fclose(fserver);
176         fserver = NULL;
177         free(buf);
178         return NULL;
179     }
180     if (sscanf(buf, "unsolved %i%n", &fld, &nchars) != 1) {
181         fprintf(stderr, "Couldn't parse response: %s\n", buf);
182         free(buf);
183         return NULL;
184     }
185     if (fld != filenum) {
186         fprintf(stderr, "Expected file number %i, not %i.\n", filenum, fld);
187         free(buf);
188         return NULL;
189     }
190     cptr = buf + nchars;
191     list = il_new(256);
192     while (*cptr && *cptr != '\n') {
193         if (sscanf(cptr, " %i%n", &fld, &nchars) != 1) {
194             fprintf(stderr, "Couldn't parse response: %s\n", buf);
195             il_free(list);
196             free(buf);
197             return NULL;
198         }
199         cptr += nchars;
200         il_append(list, fld);
201     }
202     free(buf);
203     return list;
204 }
205