cleanup vrp
[libfirm] / ir / lpp / lpp_net.c
1 /*
2  * Copyright (C) 2005-2011 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief   A client for an lpp solving server.
23  * @author  Sebastian Hack
24  */
25 #include "config.h"
26
27 #ifdef _WIN32
28 #include <winsock.h>
29 #include <io.h>
30
31 #else
32 #include <sys/time.h>
33 #include <sys/socket.h>
34 #include <sys/types.h>
35 #include <sys/resource.h>
36 #include <sys/wait.h>
37
38 #include <netinet/in.h>
39 #include <arpa/inet.h>
40 #include <netdb.h>
41 #include <unistd.h>
42
43 /* solaris fix */
44 #ifndef INADDR_NONE
45 #define INADDR_NONE (in_addr_t)(-1)
46 #endif
47
48 #endif
49
50
51 #include <signal.h>
52 #include <errno.h>
53 #include <stdlib.h>
54 #include <stdio.h>
55 #include <string.h>
56
57 #include "timing.h"
58
59 #include "lpp_net.h"
60 #include "lpp_t.h"
61 #include "lpp_comm.h"
62 #include "xmalloc.h"
63
64 #ifdef _WIN32
65 static int winsock_init(void)
66 {
67         WORD wVersionRequested;
68         WSADATA wsaData;
69         int err;
70
71         wVersionRequested = MAKEWORD( 2, 2 );
72
73         err = WSAStartup( wVersionRequested, &wsaData );
74         if ( err != 0 ) {
75                 /* Tell the user that we could not find a usable */
76                 /* WinSock DLL.                                  */
77                 return 0;
78         }
79
80         /* Confirm that the WinSock DLL supports 2.2.*/
81         /* Note that if the DLL supports versions greater    */
82         /* than 2.2 in addition to 2.2, it will still return */
83         /* 2.2 in wVersion since that is the version we      */
84         /* requested.                                        */
85
86         if ( LOBYTE( wsaData.wVersion ) != 2 ||
87                         HIBYTE( wsaData.wVersion ) != 2 ) {
88                 /* Tell the user that we could not find a usable */
89                 /* WinSock DLL.                                  */
90                 WSACleanup( );
91                 return 0;
92         }
93         return 1;
94 }
95 #endif
96
97 static int connect_tcp(const char *host, uint16_t port)
98 {
99         struct hostent     *phe;
100         struct protoent    *ppe;
101         struct sockaddr_in sin;
102         int s;
103
104 #ifdef _WIN32
105         winsock_init();
106 #endif
107
108         memset(&sin, 0, sizeof(sin));
109         sin.sin_family = AF_INET;
110         sin.sin_port   = htons(port);
111
112         if ((phe = gethostbyname(host)))
113                 memcpy(&sin.sin_addr, phe->h_addr_list[0], phe->h_length);
114         else if((sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE) {
115                 lpp_print_err("cannot get host entry for %s", host);
116                 return -1;
117         }
118
119         ppe = getprotobyname("tcp");
120         ERRNO_CHECK_RETURN(s = socket(PF_INET, SOCK_STREAM, ppe->p_proto), <, 0, -1);
121         ERRNO_CHECK_RETURN(connect(s, (struct sockaddr *) &sin, sizeof(sin)), <, 0, -1);
122
123         return s;
124 }
125
126 char **lpp_get_solvers(const char *host)
127 {
128         int fd, n;
129         char **res = NULL;
130         lpp_comm_t *comm;
131
132         ERR_CHECK_RETURN(fd = connect_tcp(host, LPP_PORT), <, 0,
133                         ("could not connect to %s", host), NULL);
134
135         comm = lpp_comm_new(fd, LPP_BUFSIZE);
136
137         lpp_writel(comm, LPP_CMD_SOLVERS);
138         lpp_flush(comm);
139         n = lpp_readl(comm);
140         res = XMALLOCN(char*, n+1);
141         res[n] = NULL;
142
143         if(n > 0) {
144                 int i;
145                 for(i = 0; i < n; ++i)
146                         res[i] = lpp_reads(comm);
147         }
148
149         lpp_writel(comm, LPP_CMD_BYE);
150         lpp_flush(comm);
151         lpp_comm_free(comm);
152         close(fd);
153         return res;
154 }
155
156 void lpp_set_dbg(const char *host, int mask)
157 {
158         int fd;
159         lpp_comm_t *comm;
160
161         ERR_CHECK_RETURN_VOID(fd = connect_tcp(host, LPP_PORT), <, 0, ("could not connect to %s", host));
162
163         comm = lpp_comm_new(fd, LPP_BUFSIZE);
164
165         lpp_writel(comm, LPP_CMD_SET_DEBUG);
166         lpp_writel(comm, mask);
167         lpp_flush(comm);
168         lpp_writel(comm, LPP_CMD_BYE);
169         lpp_flush(comm);
170         lpp_comm_free(comm);
171         close(fd);
172 }
173
174 void lpp_solve_net(lpp_t *lpp, const char *host, const char *solver)
175 {
176         char buf[1024];
177         int n, fd, ready;
178         lpp_comm_t *comm;
179         ir_timer_t *t_send, *t_recv;
180
181         ERR_CHECK_RETURN_VOID(fd = connect_tcp(host, LPP_PORT), <, 0,
182                 ("could not connect to %s", host));
183
184         comm = lpp_comm_new(fd, LPP_BUFSIZE);
185
186         /* Set the solver */
187         lpp_writel(comm, LPP_CMD_SOLVER);
188         lpp_writes(comm, solver);
189         lpp_flush(comm);
190
191         t_send = ir_timer_new();
192         t_recv = ir_timer_new();
193
194         ir_timer_start(t_send);
195         lpp_writel(comm, LPP_CMD_PROBLEM);
196         lpp_serialize(comm, lpp, 1);
197         lpp_serialize_values(comm, lpp, lpp_value_start);
198         lpp_flush(comm);
199         ir_timer_stop(t_send);
200         lpp->send_time = ir_timer_elapsed_usec(t_send);
201
202         ready = 0;
203         while (! ready) {
204                 int cmd = lpp_readl(comm);
205                 switch(cmd) {
206                         case LPP_CMD_SOLUTION:
207                                 ir_timer_push(t_recv);
208                                 lpp_deserialize_stats(comm, lpp);
209                                 lpp_deserialize_values(comm, lpp, lpp_value_solution);
210                                 ir_timer_stop(t_recv);
211                                 lpp->recv_time = ir_timer_elapsed_usec(t_recv);
212                                 ready = 1;
213                                 break;
214                         case LPP_CMD_INFO:
215                                 lpp_readbuf(comm, buf, sizeof(buf));
216                                 buf[sizeof(buf) - 1] = '\0';
217
218                                 if(lpp->log != NULL) {
219                                         fputs(buf, lpp->log);
220                                         n = strlen(buf);
221                                         if(buf[n - 1] != '\n')
222                                                 putc('\n', lpp->log);
223                                         fflush(lpp->log);
224                                 }
225                                 break;
226                         case LPP_CMD_BAD:
227                                 fprintf(stderr, "solver process died unexpectedly\n");
228                                 goto end;
229                         default:
230                                 fprintf(stderr, "invalid command: %s(%d)\n", lpp_get_cmd_name(cmd), cmd);
231                                 return;
232                 }
233         }
234
235         lpp_writel(comm, LPP_CMD_BYE);
236         lpp_flush(comm);
237
238 end:
239         lpp_comm_free(comm);
240 #ifdef _WIN32
241         closesocket(fd);
242 #else
243         close(fd);
244 #endif
245 }