source: roaraudio/libroar/socket.c @ 376:9547ed19bc09

Last change on this file since 376:9547ed19bc09 was 376:9547ed19bc09, checked in by phi, 16 years ago

maybe this call works...

File size: 8.0 KB
Line 
1//socket.c:
2
3#include "libroar.h"
4
5/* old...
6#define MODE_LISTEN  1
7#define MODE_CONNECT 2
8*/
9#define MODE_LISTEN  ROAR_SOCKET_MODE_LISTEN
10#define MODE_CONNECT ROAR_SOCKET_MODE_CONNECT
11
12int roar_socket_new_tcp (void) {
13 int fh;
14 int opt = IPTOS_LOWDELAY;
15// int extra_flags = TCP_NODELAY;
16
17 fh = socket(PF_INET, SOCK_STREAM, 0);
18
19/*
20phi@ph7:libroar $ IP_TOS
21phi@ph7:libroar $ IPTOS_LOWDELAY
22*/
23
24 setsockopt(fh, IPPROTO_IP, IP_TOS, &opt, sizeof(int));
25
26 return fh;
27}
28
29int roar_socket_new_udp (void) {
30 int fh;
31 int opt = IPTOS_LOWDELAY;
32
33 fh = socket(PF_INET, SOCK_DGRAM, 0);
34
35 setsockopt(fh, IPPROTO_IP, IP_TOS, &opt, sizeof(int));
36
37 return fh;
38}
39
40int roar_socket_new_unix (void) {
41 int fh;
42
43 fh = socket(AF_UNIX, SOCK_STREAM, 0);
44
45 return fh;
46}
47
48int roar_socket_nonblock(int fh, int state) {
49 int flags;
50
51 if ( (flags = fcntl(fh, F_GETFL, 0)) == -1 ) {
52  ROAR_ERR("roar_socket_nonblock(fh=%i, state=%i): Can not read flags: %s", fh, state, strerror(errno));
53  ROAR_DBG("roar_socket_nonblock(fh=%i, state=%i) = -1", fh, state);
54  return -1;
55 }
56
57 flags |= O_NONBLOCK;
58
59 if ( state == ROAR_SOCKET_BLOCK )
60  flags -= O_NONBLOCK;
61
62 if ( fcntl(fh, F_SETFL, flags) == -1 ) {
63  ROAR_ERR("roar_socket_nonblock(fh=%i, state=%i): Can not set flags: %s", fh, state, strerror(errno));
64  ROAR_DBG("roar_socket_nonblock(fh=%i, state=%i) = -1", fh, state);
65  return -1;
66 }
67
68 ROAR_DBG("roar_socket_nonblock(fh=%i, state=%i) = 0", fh, state);
69 return 0;
70}
71
72int roar_socket_dup_udp_local_end (int fh) {
73 int                  n              = -1;
74 int                  flags          = -1;
75 struct sockaddr_in   socket_addr;
76 socklen_t            len            = sizeof(struct sockaddr_in);
77
78 if ( (flags = fcntl(fh, F_GETFL, 0)) == -1 ) {
79  ROAR_WARN("roar_socket_dup_udp_local_end(fh=%i): Can not read flags: %s", fh, strerror(errno));
80 }
81
82 if ( getsockname(fh, (struct sockaddr *)&socket_addr, &len) == -1 ) {
83  return -1;
84 }
85
86 if ( socket_addr.sin_family != AF_INET ) {
87  return -1;
88 }
89
90 n = roar_socket_new_udp();
91
92 if ( n == -1 )
93  return -1;
94
95//  if ( mode_func(fh, (struct sockaddr *)&socket_addr, sizeof(struct sockaddr_in)) == -1 ) {
96 if ( bind(n, (struct sockaddr *)&socket_addr, len) == -1 ) {
97  close(n);
98  return -1;
99 }
100
101 if ( flags != -1 ) {
102  if ( fcntl(fh, F_SETFL, flags) == -1 ) {
103   ROAR_WARN("roar_socket_dup_udp_local_end(fh=%i): Can not set flags: %s", fh, strerror(errno));
104   return -1;
105  }
106 }
107
108
109 return n;
110}
111
112int roar_socket_listen  (int type, char * host, int port) {
113 return roar_socket_open(MODE_LISTEN, type, host, port);
114}
115
116int roar_socket_connect (char * host, int port) {
117 char * proxy_type = getenv("ROAR_PROXY");
118
119 if ( proxy_type == NULL || strcmp(proxy_type, "") == 0 ) {
120  return roar_socket_open(MODE_CONNECT, ROAR_SOCKET_TYPE_UNKNOWN, host, port);
121 } else {
122  return roar_socket_open_proxy(MODE_CONNECT, ROAR_SOCKET_TYPE_UNKNOWN, host, port, proxy_type);
123 }
124}
125
126int roar_socket_open (int mode, int type, char * host, int port) {
127// int type = ROAR_SOCKET_TYPE_INET;
128 int fh;
129 struct sockaddr_in   socket_addr;
130 struct sockaddr_un   socket_addr_un;
131 struct hostent     * he;
132 //unsigned int host_div = 0;
133 int (*mode_func)(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen) = connect; // default is to connect
134
135 if ( mode == MODE_LISTEN )
136  mode_func = bind;
137
138 if ( type == ROAR_SOCKET_TYPE_UNKNOWN ) {
139  type = ROAR_SOCKET_TYPE_INET;
140  if ( *host == '/' ) {
141   type = ROAR_SOCKET_TYPE_UNIX;
142  } else if ( strcmp(host, "+fork") == 0 ) {
143   type = ROAR_SOCKET_TYPE_FORK;
144  }
145 }
146
147
148 ROAR_DBG("roar_socket_open(*): type=%s, host='%s', port=%i",
149             type == ROAR_SOCKET_TYPE_UNIX ? "UNIX" : "INET", host, port);
150
151 memset(&socket_addr   , 0, sizeof(socket_addr));
152 memset(&socket_addr_un, 0, sizeof(socket_addr_un));
153 memset(&he,             0, sizeof(he));               // FIXME: we have a valid pointer in here????
154
155
156 if ( type == ROAR_SOCKET_TYPE_INET ) {
157
158  if ( (he = gethostbyname(host)) == NULL ) {
159   ROAR_ERR("roar_socket_open(*): Can\'t resolve host name '%s'",
160                     host);
161   return -1;
162  }
163
164  memcpy((struct in_addr *)&socket_addr.sin_addr, he->h_addr, sizeof(struct in_addr));
165
166  /* set the connect information */
167  socket_addr.sin_family = AF_INET;
168  socket_addr.sin_port = htons( port );
169
170  fh = roar_socket_new_tcp();
171
172  if ( mode_func(fh, (struct sockaddr *)&socket_addr, sizeof(struct sockaddr_in)) == -1 ) {
173   ROAR_DBG("roar_socket_open(*): Can not connect/bind: %s", strerror(errno));
174   close(fh);
175   return -1;
176  }
177  // hey! we have a socket...
178 } else if ( type == ROAR_SOCKET_TYPE_UNIX ) {
179  socket_addr_un.sun_family = AF_UNIX;
180  strncpy(socket_addr_un.sun_path, host, sizeof(socket_addr_un.sun_path) - 1);
181
182  fh = roar_socket_new_unix();
183
184  if ( mode_func(fh, (struct sockaddr *)&socket_addr_un, sizeof(struct sockaddr_un)) == -1 ) {
185   ROAR_DBG("roar_socket_open(*): Can not connect/bind: %s", strerror(errno));
186   close(fh);
187   return -1;
188  }
189 } else if ( type == ROAR_SOCKET_TYPE_FORK ) {
190  return roar_socket_open_fork(mode, host, port);
191 } else if ( type == ROAR_SOCKET_TYPE_FILE ) {
192  return roar_socket_open_file(mode, host, port);
193 } else {
194  return -1;
195 }
196
197 if ( mode == MODE_LISTEN )
198  if ( listen(fh, ROAR_SOCKET_QUEUE_LEN) == -1 ) {
199   close(fh);
200   return -1;
201  }
202
203 return fh;
204}
205
206int roar_socket_open_fork  (int mode, char * host, int port) {
207 int socks[2];
208 int r;
209 char fhstr[8];
210
211 if ( mode == MODE_LISTEN )
212  return -1;
213
214 if ( socketpair(AF_UNIX, SOCK_STREAM, 0, socks) == -1 ) {
215  return -1;
216 }
217
218 r = fork();
219
220 if ( r == -1 ) { // error!
221  ROAR_ERR("roar_socket_open_fork(*): Can not fork: %s", strerror(errno));
222  close(socks[0]);
223  close(socks[1]);
224  return -1;
225 } else if ( r == 0 ) { // we are the child
226  close(socks[0]);
227
228  close(ROAR_STDIN ); // we do not want roard to have any standard input
229  close(ROAR_STDOUT); // STDOUT is also not needed, so we close it,
230                      // but STDERR we keep open for error messages.
231
232  snprintf(fhstr, 7, "%i", socks[1]);
233
234  execlp("roard", "roard", "--terminate", "--no-listen", "--client-fh", fhstr, NULL);
235
236  // we are still alive?
237  ROAR_ERR("roar_socket_open_fork(*): alive after exec(), that's bad!");
238  _exit(1);
239 } else { // we are the parent
240  close(socks[1]);
241  return socks[0];
242 }
243
244 return -1;
245}
246
247int roar_socket_open_file  (int mode, char * host, int port) {
248 int fh;
249
250 if ( mode == MODE_LISTEN )
251  return -1;
252
253 if ( (fh = open(host, O_RDONLY, 0644)) == -1 ) {
254  ROAR_ERR("roar_socket_open_file(*): Can not open file %s: %s", host, strerror(errno));
255 }
256
257 return fh;
258}
259
260// --- [ PROXY CODE ] ---
261
262// generic proxy code:
263
264int roar_socket_open_proxy (int mode, int type, char * host, int port, char * proxy_type) {
265 int    proxy_port;
266 char   proxy_host[ROAR_SOCKET_MAX_HOSTNAMELEN];
267 char * proxy_addr;
268 int    i;
269 int    fh;
270
271 // TODO: change this so we support listen() proxys (ssh -R)
272 if ( mode != MODE_CONNECT )
273  return -1;
274
275 if ( !strcmp(proxy_type, "socks4a") ) { // for TOR, the only supported type at the moment
276  proxy_addr = getenv("socks_proxy");
277
278  proxy_port = 9050; // TOR's default port
279
280  if ( proxy_addr == NULL )
281   return -1;
282
283  for (i = 0; proxy_addr[i] != 0 && proxy_addr[i] != ':' && i < ROAR_SOCKET_MAX_HOSTNAMELEN; i++)
284   proxy_host[i] = proxy_addr[i];
285  proxy_host[i] = 0;
286
287  if ( i == 0 ) // no hostname found
288   return -1;
289
290  if ( proxy_addr[i] == ':' )
291   proxy_port = atoi(&proxy_addr[i+1]);
292
293  if ( (fh = roar_socket_open(mode, type, proxy_host, proxy_port)) == -1) {
294   return -1;
295  }
296
297  if ( roar_socket_open_socks4a(mode, fh, host, port) == -1 ) {
298   close(fh);
299   return -1;
300  }
301
302  return fh;
303 } else {
304  return -1; // unknown type
305 }
306}
307
308// protocoll dependet proxy code:
309
310int roar_socket_open_socks4a(int mode, int fh, char * host, int port) {
311 char buf[9];
312 int  len;
313
314 buf[0] = 0x04;
315 buf[1] = mode == MODE_CONNECT ? 0x01 : 0x02;
316 *((uint16_t*)&buf[2]) = htons(port);
317 buf[4] = 0x00;
318 buf[5] = 0x00;
319 buf[6] = 0x00;
320 buf[7] = 0x01;
321 buf[8] = 0x00;
322
323 if ( write(fh, buf, 9) != 9 )
324  return -1;
325
326 len = strlen(host);
327
328 if ( write(fh, host, len) != len )
329  return -1;
330
331 if ( write(fh, "\0", 1) != 1 )
332  return -1;
333
334 if ( read(fh, buf, 8) != 8 )
335  return -1;
336
337 if ( buf[1] != 0x5a )
338  return -1;
339
340 return 0;
341}
342
343//ll
Note: See TracBrowser for help on using the repository browser.