source: roaraudio/libroar/socket.c @ 375:1a8441809146

Last change on this file since 375:1a8441809146 was 375:1a8441809146, checked in by phi, 16 years ago

added a prototype for a call to reate a new UDP socket with same local end as a given one

File size: 7.1 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 return -1;
74}
75
76int roar_socket_listen  (int type, char * host, int port) {
77 return roar_socket_open(MODE_LISTEN, type, host, port);
78}
79
80int roar_socket_connect (char * host, int port) {
81 char * proxy_type = getenv("ROAR_PROXY");
82
83 if ( proxy_type == NULL || strcmp(proxy_type, "") == 0 ) {
84  return roar_socket_open(MODE_CONNECT, ROAR_SOCKET_TYPE_UNKNOWN, host, port);
85 } else {
86  return roar_socket_open_proxy(MODE_CONNECT, ROAR_SOCKET_TYPE_UNKNOWN, host, port, proxy_type);
87 }
88}
89
90int roar_socket_open (int mode, int type, char * host, int port) {
91// int type = ROAR_SOCKET_TYPE_INET;
92 int fh;
93 struct sockaddr_in   socket_addr;
94 struct sockaddr_un   socket_addr_un;
95 struct hostent     * he;
96 //unsigned int host_div = 0;
97 int (*mode_func)(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen) = connect; // default is to connect
98
99 if ( mode == MODE_LISTEN )
100  mode_func = bind;
101
102 if ( type == ROAR_SOCKET_TYPE_UNKNOWN ) {
103  type = ROAR_SOCKET_TYPE_INET;
104  if ( *host == '/' ) {
105   type = ROAR_SOCKET_TYPE_UNIX;
106  } else if ( strcmp(host, "+fork") == 0 ) {
107   type = ROAR_SOCKET_TYPE_FORK;
108  }
109 }
110
111
112 ROAR_DBG("roar_socket_open(*): type=%s, host='%s', port=%i",
113             type == ROAR_SOCKET_TYPE_UNIX ? "UNIX" : "INET", host, port);
114
115 memset(&socket_addr   , 0, sizeof(socket_addr));
116 memset(&socket_addr_un, 0, sizeof(socket_addr_un));
117 memset(&he,             0, sizeof(he));               // FIXME: we have a valid pointer in here????
118
119
120 if ( type == ROAR_SOCKET_TYPE_INET ) {
121
122  if ( (he = gethostbyname(host)) == NULL ) {
123   ROAR_ERR("roar_socket_open(*): Can\'t resolve host name '%s'",
124                     host);
125   return -1;
126  }
127
128  memcpy((struct in_addr *)&socket_addr.sin_addr, he->h_addr, sizeof(struct in_addr));
129
130  /* set the connect information */
131  socket_addr.sin_family = AF_INET;
132  socket_addr.sin_port = htons( port );
133
134  fh = roar_socket_new_tcp();
135
136  if ( mode_func(fh, (struct sockaddr *)&socket_addr, sizeof(struct sockaddr_in)) == -1 ) {
137   ROAR_DBG("roar_socket_open(*): Can not connect/bind: %s", strerror(errno));
138   close(fh);
139   return -1;
140  }
141  // hey! we have a socket...
142 } else if ( type == ROAR_SOCKET_TYPE_UNIX ) {
143  socket_addr_un.sun_family = AF_UNIX;
144  strncpy(socket_addr_un.sun_path, host, sizeof(socket_addr_un.sun_path) - 1);
145
146  fh = roar_socket_new_unix();
147
148  if ( mode_func(fh, (struct sockaddr *)&socket_addr_un, sizeof(struct sockaddr_un)) == -1 ) {
149   ROAR_DBG("roar_socket_open(*): Can not connect/bind: %s", strerror(errno));
150   close(fh);
151   return -1;
152  }
153 } else if ( type == ROAR_SOCKET_TYPE_FORK ) {
154  return roar_socket_open_fork(mode, host, port);
155 } else if ( type == ROAR_SOCKET_TYPE_FILE ) {
156  return roar_socket_open_file(mode, host, port);
157 } else {
158  return -1;
159 }
160
161 if ( mode == MODE_LISTEN )
162  if ( listen(fh, ROAR_SOCKET_QUEUE_LEN) == -1 ) {
163   close(fh);
164   return -1;
165  }
166
167 return fh;
168}
169
170int roar_socket_open_fork  (int mode, char * host, int port) {
171 int socks[2];
172 int r;
173 char fhstr[8];
174
175 if ( mode == MODE_LISTEN )
176  return -1;
177
178 if ( socketpair(AF_UNIX, SOCK_STREAM, 0, socks) == -1 ) {
179  return -1;
180 }
181
182 r = fork();
183
184 if ( r == -1 ) { // error!
185  ROAR_ERR("roar_socket_open_fork(*): Can not fork: %s", strerror(errno));
186  close(socks[0]);
187  close(socks[1]);
188  return -1;
189 } else if ( r == 0 ) { // we are the child
190  close(socks[0]);
191
192  close(ROAR_STDIN ); // we do not want roard to have any standard input
193  close(ROAR_STDOUT); // STDOUT is also not needed, so we close it,
194                      // but STDERR we keep open for error messages.
195
196  snprintf(fhstr, 7, "%i", socks[1]);
197
198  execlp("roard", "roard", "--terminate", "--no-listen", "--client-fh", fhstr, NULL);
199
200  // we are still alive?
201  ROAR_ERR("roar_socket_open_fork(*): alive after exec(), that's bad!");
202  _exit(1);
203 } else { // we are the parent
204  close(socks[1]);
205  return socks[0];
206 }
207
208 return -1;
209}
210
211int roar_socket_open_file  (int mode, char * host, int port) {
212 int fh;
213
214 if ( mode == MODE_LISTEN )
215  return -1;
216
217 if ( (fh = open(host, O_RDONLY, 0644)) == -1 ) {
218  ROAR_ERR("roar_socket_open_file(*): Can not open file %s: %s", host, strerror(errno));
219 }
220
221 return fh;
222}
223
224// --- [ PROXY CODE ] ---
225
226// generic proxy code:
227
228int roar_socket_open_proxy (int mode, int type, char * host, int port, char * proxy_type) {
229 int    proxy_port;
230 char   proxy_host[ROAR_SOCKET_MAX_HOSTNAMELEN];
231 char * proxy_addr;
232 int    i;
233 int    fh;
234
235 // TODO: change this so we support listen() proxys (ssh -R)
236 if ( mode != MODE_CONNECT )
237  return -1;
238
239 if ( !strcmp(proxy_type, "socks4a") ) { // for TOR, the only supported type at the moment
240  proxy_addr = getenv("socks_proxy");
241
242  proxy_port = 9050; // TOR's default port
243
244  if ( proxy_addr == NULL )
245   return -1;
246
247  for (i = 0; proxy_addr[i] != 0 && proxy_addr[i] != ':' && i < ROAR_SOCKET_MAX_HOSTNAMELEN; i++)
248   proxy_host[i] = proxy_addr[i];
249  proxy_host[i] = 0;
250
251  if ( i == 0 ) // no hostname found
252   return -1;
253
254  if ( proxy_addr[i] == ':' )
255   proxy_port = atoi(&proxy_addr[i+1]);
256
257  if ( (fh = roar_socket_open(mode, type, proxy_host, proxy_port)) == -1) {
258   return -1;
259  }
260
261  if ( roar_socket_open_socks4a(mode, fh, host, port) == -1 ) {
262   close(fh);
263   return -1;
264  }
265
266  return fh;
267 } else {
268  return -1; // unknown type
269 }
270}
271
272// protocoll dependet proxy code:
273
274int roar_socket_open_socks4a(int mode, int fh, char * host, int port) {
275 char buf[9];
276 int  len;
277
278 buf[0] = 0x04;
279 buf[1] = mode == MODE_CONNECT ? 0x01 : 0x02;
280 *((uint16_t*)&buf[2]) = htons(port);
281 buf[4] = 0x00;
282 buf[5] = 0x00;
283 buf[6] = 0x00;
284 buf[7] = 0x01;
285 buf[8] = 0x00;
286
287 if ( write(fh, buf, 9) != 9 )
288  return -1;
289
290 len = strlen(host);
291
292 if ( write(fh, host, len) != len )
293  return -1;
294
295 if ( write(fh, "\0", 1) != 1 )
296  return -1;
297
298 if ( read(fh, buf, 8) != 8 )
299  return -1;
300
301 if ( buf[1] != 0x5a )
302  return -1;
303
304 return 0;
305}
306
307//ll
Note: See TracBrowser for help on using the repository browser.