source: roaraudio/libroar/socket.c @ 2:2d5e843739a3

Last change on this file since 2:2d5e843739a3 was 2:2d5e843739a3, checked in by phi, 16 years ago

added socks4a support

File size: 4.6 KB
Line 
1//socket.c:
2
3#include "libroar.h"
4
5#define MODE_LISTEN  1
6#define MODE_CONNECT 2
7
8int roar_socket_new_tcp (void) {
9 int fh;
10// int extra_flags = TCP_NODELAY;
11
12 fh = socket(PF_INET, SOCK_STREAM, 0);
13
14 return fh;
15}
16
17int roar_socket_new_unix (void) {
18 int fh;
19
20 fh = socket(AF_UNIX, SOCK_STREAM, 0);
21
22 return fh;
23}
24
25int roar_socket_nonblock(int fh, int state) {
26 int flags;
27
28 if ( (flags = fcntl(fh, F_GETFL, 0)) == -1 ) {
29  ROAR_ERR("roar_socket_nonblock(fh=%i, state=%i): Can not read flags: %s", fh, state, strerror(errno));
30  ROAR_DBG("roar_socket_nonblock(fh=%i, state=%i) = -1", fh, state);
31  return -1;
32 }
33
34 flags |= O_NONBLOCK;
35
36 if ( state == ROAR_SOCKET_BLOCK )
37  flags -= O_NONBLOCK;
38
39 if ( fcntl(fh, F_SETFL, flags) == -1 ) {
40  ROAR_ERR("roar_socket_nonblock(fh=%i, state=%i): Can not set flags: %s", fh, state, strerror(errno));
41  ROAR_DBG("roar_socket_nonblock(fh=%i, state=%i) = -1", fh, state);
42  return -1;
43 }
44
45 ROAR_DBG("roar_socket_nonblock(fh=%i, state=%i) = 0", fh, state);
46 return 0;
47}
48
49int roar_socket_listen  (int type, char * host, int port) {
50 return roar_socket_open(MODE_LISTEN, type, host, port);
51}
52
53int roar_socket_connect (char * host, int port) {
54 char * proxy_type = getenv("ROAR_PROXY");
55
56 if ( proxy_type == NULL || strcmp(proxy_type, "") == 0 ) {
57  return roar_socket_open(MODE_CONNECT, ROAR_SOCKET_TYPE_UNKNOWN, host, port);
58 } else {
59  return roar_socket_open_proxy(MODE_CONNECT, ROAR_SOCKET_TYPE_UNKNOWN, host, port, proxy_type);
60 }
61}
62
63int roar_socket_open (int mode, int type, char * host, int port) {
64// int type = ROAR_SOCKET_TYPE_INET;
65 int fh;
66 struct sockaddr_in   socket_addr;
67 struct hostent     * he;
68 //unsigned int host_div = 0;
69 int (*mode_func)(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen) = connect; // default is to connect
70
71 if ( mode == MODE_LISTEN )
72  mode_func = bind;
73
74 if ( type == ROAR_SOCKET_TYPE_UNKNOWN ) {
75  type = ROAR_SOCKET_TYPE_INET;
76  if ( *host == '/' )
77   type = ROAR_SOCKET_TYPE_UNIX;
78 }
79
80
81 ROAR_DBG("roar_socket_open(*): type=%s, host='%s', port=%i",
82             type == ROAR_SOCKET_TYPE_UNIX ? "UNIX" : "INET", host, port);
83
84 memset(&socket_addr, 0, sizeof(socket_addr));
85 memset(&he,          0, sizeof(he));
86
87
88 if ( type == ROAR_SOCKET_TYPE_INET ) {
89
90  if ( (he = gethostbyname(host)) == NULL ) {
91   ROAR_ERR("roar_socket_open(*): Can\'t resolve host name '%s'",
92                     host);
93   return -1;
94  }
95
96  memcpy((struct in_addr *)&socket_addr.sin_addr, he->h_addr, sizeof(struct in_addr));
97
98  /* set the connect information */
99  socket_addr.sin_family = AF_INET;
100  socket_addr.sin_port = htons( port );
101
102  fh = roar_socket_new_tcp();
103
104  if ( mode_func(fh, (struct sockaddr *)&socket_addr, sizeof(struct sockaddr_in)) == -1 ) {
105   ROAR_DBG("roar_socket_open(*): Can not connect/bind: %s", strerror(errno));
106   close(fh);
107   return -1;
108  }
109  // hey! we have a socket...
110 } else {
111  fh = roar_socket_new_unix();
112  close(fh);
113  return -1;
114 }
115
116 if ( mode == MODE_LISTEN )
117  if ( listen(fh, ROAR_SOCKET_QUEUE_LEN) == -1 ) {
118   close(fh);
119   return -1;
120  }
121
122 return fh;
123}
124
125// --- [ PROXY CODE ] ---
126
127// generic proxy code:
128
129int roar_socket_open_proxy (int mode, int type, char * host, int port, char * proxy_type) {
130 int    proxy_port;
131 char   proxy_host[ROAR_SOCKET_MAX_HOSTNAMELEN];
132 char * proxy_addr;
133 int    i;
134 int    fh;
135
136 // TODO: change this so we support listen() proxys (ssh -R)
137 if ( mode != MODE_CONNECT )
138  return -1;
139
140 if ( !strcmp(proxy_type, "socks4a") ) { // for TOR, the only supported type at the moment
141  proxy_addr = getenv("socks_proxy");
142
143  proxy_port = 9050; // TOR's default port
144
145  if ( proxy_addr == NULL )
146   return -1;
147
148  for (i = 0; proxy_addr[i] != 0 && proxy_addr[i] != ':' && i < ROAR_SOCKET_MAX_HOSTNAMELEN; i++)
149   proxy_host[i] = proxy_addr[i];
150  proxy_host[i] = 0;
151
152  if ( i == 0 ) // no hostname found
153   return -1;
154
155  if ( proxy_addr[i] == ':' )
156   proxy_port = atoi(&proxy_addr[i+1]);
157
158  if ( (fh = roar_socket_open(mode, type, proxy_host, proxy_port)) == -1) {
159   return -1;
160  }
161
162  if ( roar_socket_open_socks4a(mode, fh, host, port) == -1 ) {
163   close(fh);
164   return -1;
165  }
166
167  return fh;
168 } else {
169  return -1; // unknown type
170 }
171}
172
173// protocoll dependet proxy code:
174
175int roar_socket_open_socks4a(int mode, int fh, char * host, int port) {
176 char buf[9];
177 int  len;
178
179 buf[0] = 0x04;
180 buf[1] = mode == MODE_CONNECT ? 0x01 : 0x02;
181 *((uint16_t*)&buf[2]) = htons(port);
182 buf[4] = 0x00;
183 buf[5] = 0x00;
184 buf[6] = 0x00;
185 buf[7] = 0x01;
186 buf[8] = 0x00;
187
188 if ( write(fh, buf, 9) != 9 )
189  return -1;
190
191 len = strlen(host);
192
193 if ( write(fh, host, len) != len )
194  return -1;
195
196 if ( write(fh, "\0", 1) != 1 )
197  return -1;
198
199 if ( read(fh, buf, 8) != 8 )
200  return -1;
201
202 if ( buf[1] != 0x5a )
203  return -1;
204
205 return 0;
206}
207
208//ll
Note: See TracBrowser for help on using the repository browser.