mesa: added new linux-gallium and linux-gallium-debug configs
[mesa.git] / progs / xdemos / ipc.c
1 /* Copyright (c) 2003 Tungsten Graphics, Inc.
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining
4 * a copy of this software and associated documentation files ("the
5 * Software"), to deal in the Software without restriction, including
6 * without limitation the rights to use, copy, modify, merge, publish,
7 * distribute, sublicense, and/or sell copies of the Software, and to
8 * permit persons to whom the Software is furnished to do so, subject to
9 * the following conditions: The above copyright notice, the Tungsten
10 * Graphics splash screen, and this permission notice shall be included
11 * in all copies or substantial portions of the Software. THE SOFTWARE
12 * IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
15 * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
17 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
18 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 */
20
21 /*
22 * Simple IPC API
23 * Brian Paul
24 */
25
26
27 #include <assert.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <sys/types.h>
31 #include <netinet/in.h>
32 #include <netinet/tcp.h>
33 #include <arpa/inet.h>
34 #include <netdb.h>
35 #include <unistd.h>
36 #include <sys/socket.h>
37 #include "ipc.h"
38
39 #if defined(IRIX) || defined(irix)
40 typedef int socklen_t;
41 #endif
42
43 #define NO_DELAY 1
44
45 #define DEFAULT_MASTER_PORT 7011
46
47
48 /*
49 * Return my hostname in <nameOut>.
50 * Return 1 for success, 0 for error.
51 */
52 int
53 MyHostName(char *nameOut, int maxNameLength)
54 {
55 int k = gethostname(nameOut, maxNameLength);
56 return k==0;
57 }
58
59
60 /*
61 * Create a socket attached to a port. Later, we can call AcceptConnection
62 * on the socket returned from this function.
63 * Return the new socket number or -1 if error.
64 */
65 int
66 CreatePort(int *port)
67 {
68 char hostname[1000];
69 struct sockaddr_in servaddr;
70 struct hostent *hp;
71 int so_reuseaddr = 1;
72 int tcp_nodelay = 1;
73 int sock, k;
74
75 /* create socket */
76 sock = socket(AF_INET, SOCK_STREAM, 0);
77 assert(sock > 2);
78
79 /* get my host name */
80 k = gethostname(hostname, 1000);
81 assert(k == 0);
82
83 /* get hostent info */
84 hp = gethostbyname(hostname);
85 assert(hp);
86
87 /* initialize the servaddr struct */
88 memset(&servaddr, 0, sizeof(servaddr) );
89 servaddr.sin_family = AF_INET;
90 servaddr.sin_port = htons((unsigned short) (*port));
91 memcpy((char *) &servaddr.sin_addr, hp->h_addr,
92 sizeof(servaddr.sin_addr));
93
94 /* deallocate when we exit */
95 k = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
96 (char *) &so_reuseaddr, sizeof(so_reuseaddr));
97 assert(k==0);
98
99 /* send packets immediately */
100 #if NO_DELAY
101 k = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
102 (char *) &tcp_nodelay, sizeof(tcp_nodelay));
103 assert(k==0);
104 #endif
105
106 if (*port == 0)
107 *port = DEFAULT_MASTER_PORT;
108
109 k = 1;
110 while (k && (*port < 65534)) {
111 /* bind our address to the socket */
112 servaddr.sin_port = htons((unsigned short) (*port));
113 k = bind(sock, (struct sockaddr *) &servaddr, sizeof(servaddr));
114 if (k)
115 *port = *port + 1;
116 }
117
118 #if 0
119 printf("###### Real Port: %d\n", *port);
120 #endif
121
122 /* listen for connections */
123 k = listen(sock, 100);
124 assert(k == 0);
125
126 return sock;
127 }
128
129
130 /*
131 * Accept a connection on the named socket.
132 * Return a new socket for the new connection, or -1 if error.
133 */
134 int
135 AcceptConnection(int socket)
136 {
137 struct sockaddr addr;
138 socklen_t addrLen;
139 int newSock;
140
141 addrLen = sizeof(addr);
142 newSock = accept(socket, &addr, &addrLen);
143 if (newSock == 1)
144 return -1;
145 else
146 return newSock;
147 }
148
149
150 /*
151 * Contact the server running on the given host on the named port.
152 * Return socket number or -1 if error.
153 */
154 int
155 Connect(const char *hostname, int port)
156 {
157 struct sockaddr_in servaddr;
158 struct hostent *hp;
159 int sock, k;
160 int tcp_nodelay = 1;
161
162 assert(port);
163
164 sock = socket(AF_INET, SOCK_STREAM, 0);
165 assert(sock >= 0);
166
167 hp = gethostbyname(hostname);
168 assert(hp);
169
170 memset(&servaddr, 0, sizeof(servaddr));
171 servaddr.sin_family = AF_INET;
172 servaddr.sin_port = htons((unsigned short) port);
173 memcpy((char *) &servaddr.sin_addr, hp->h_addr, sizeof(servaddr.sin_addr));
174
175 k = connect(sock, (struct sockaddr *) &servaddr, sizeof(servaddr));
176 if (k != 0) {
177 perror("Connect:");
178 return -1;
179 }
180
181 #if NO_DELAY
182 /* send packets immediately */
183 k = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
184 (char *) &tcp_nodelay, sizeof(tcp_nodelay));
185 assert(k==0);
186 #endif
187
188 return sock;
189 }
190
191
192 void
193 CloseSocket(int socket)
194 {
195 close(socket);
196 }
197
198
199 int
200 SendData(int socket, const void *data, int bytes)
201 {
202 int sent = 0;
203 int b;
204
205 while (sent < bytes) {
206 b = write(socket, (char *) data + sent, bytes - sent);
207 if (b <= 0)
208 return -1; /* something broke */
209 sent += b;
210 }
211 return sent;
212 }
213
214
215 int
216 ReceiveData(int socket, void *data, int bytes)
217 {
218 int received = 0, b;
219
220 while (received < bytes) {
221 b = read(socket, (char *) data + received, bytes - received);
222 if (b <= 0)
223 return -1;
224 received += b;
225 }
226 return received;
227 }
228
229
230 int
231 SendString(int socket, const char *str)
232 {
233 const int len = strlen(str);
234 int sent, b;
235
236 /* first, send a 4-byte length indicator */
237 b = write(socket, &len, sizeof(len));
238 if (b <= 0)
239 return -1;
240
241 sent = SendData(socket, str, len);
242 assert(sent == len);
243 return sent;
244 }
245
246
247 int
248 ReceiveString(int socket, char *str, int maxLen)
249 {
250 int len, received, b;
251
252 /* first, read 4 bytes to see how long of string to receive */
253 b = read(socket, &len, sizeof(len));
254 if (b <= 0)
255 return -1;
256
257 assert(len <= maxLen); /* XXX fix someday */
258 assert(len >= 0);
259 received = ReceiveData(socket, str, len);
260 assert(received != -1);
261 assert(received == len);
262 str[len] = 0;
263 return received;
264 }