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