Mercurial > hg > nnchat
comparison libnnchat.c @ 354:c01e42fc9adb
More work on SOCKS proxy support, should work now.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 23 Jun 2011 08:26:48 +0300 |
parents | b54c8545dcb0 |
children | ba2aa110755b |
comparison
equal
deleted
inserted
replaced
353:83ae825bb8c1 | 354:c01e42fc9adb |
---|---|
70 conn->msgfunc(conn, fmt, ap); | 70 conn->msgfunc(conn, fmt, ap); |
71 va_end(ap); | 71 va_end(ap); |
72 } | 72 } |
73 } | 73 } |
74 | 74 |
75 struct hostent *nn_resolve_host(nn_conn_t *conn, const char *name) | |
76 { | |
77 struct hostent *res = gethostbyname(name); | |
78 if (res == NULL) | |
79 nn_conn_err(conn, "Could not resolve hostname: %s\n", strerror(h_errno)); | |
80 else | |
81 nn_conn_msg(conn, "True hostname for %s is %s\n", name, res->h_name); | |
82 | |
83 return res; | |
84 } | |
85 | |
75 static const char *nn_proxy_types[] = { | 86 static const char *nn_proxy_types[] = { |
76 "none", | 87 "none", |
77 "SOCKS 4", | 88 "SOCKS 4", |
78 "SOCKS 4a", | 89 "SOCKS 4a", |
79 NULL | 90 NULL |
80 }; | 91 }; |
81 | 92 |
82 nn_conn_t * nn_conn_open( | 93 |
83 void (*errfunc)(struct _nn_conn_t *conn, const char *fmt, va_list ap), | 94 nn_conn_t * nn_conn_new( |
84 void (*msgfunc)(struct _nn_conn_t *conn, const char *fmt, va_list ap), | 95 void (*errfunc)(nn_conn_t *conn, const char *fmt, va_list ap), |
85 int ptype, int pport, struct in_addr *paddr, | 96 void (*msgfunc)(nn_conn_t *conn, const char *fmt, va_list ap)) |
86 struct in_addr *addr, const int port, const char *host) | |
87 { | 97 { |
88 nn_conn_t *conn = th_calloc(1, sizeof(nn_conn_t)); | 98 nn_conn_t *conn = th_calloc(1, sizeof(nn_conn_t)); |
99 | |
100 if (conn == NULL) | |
101 return NULL; | |
102 | |
103 conn->errfunc = errfunc; | |
104 conn->msgfunc = msgfunc; | |
105 | |
106 return conn; | |
107 } | |
108 | |
109 int nn_conn_set_proxy(nn_conn_t *conn, int type, int port, const char *host) | |
110 { | |
111 if (conn == NULL) | |
112 return -1; | |
113 | |
114 conn->proxy.type = type; | |
115 conn->proxy.port = port; | |
116 conn->proxy.host = th_strdup(host); | |
117 | |
118 if (host != NULL) { | |
119 conn->proxy.hst = nn_resolve_host(conn, host); | |
120 if (conn->proxy.hst != NULL) | |
121 conn->proxy.addr = *(struct in_addr *) (conn->proxy.hst->h_addr); | |
122 else { | |
123 conn->proxy.addr.s_addr = 0; | |
124 } | |
125 } else | |
126 return -2; | |
127 | |
128 return 0; | |
129 } | |
130 | |
131 int nn_conn_open(nn_conn_t *conn, const int port, const char *host) | |
132 { | |
89 struct sockaddr_in dest; | 133 struct sockaddr_in dest; |
90 static const char *userid = "James Bond"; | 134 static const char *userid = "James Bond"; |
91 | 135 |
92 if (conn == NULL) | 136 if (conn == NULL) |
93 return NULL; | 137 return -1; |
94 | |
95 /* Initialize data */ | |
96 conn->errfunc = errfunc; | |
97 conn->msgfunc = msgfunc; | |
98 | |
99 conn->proxy.type = ptype; | |
100 conn->proxy.port = pport; | |
101 if (paddr != NULL) | |
102 conn->proxy.addr = *paddr; | |
103 | 138 |
104 conn->port = port; | 139 conn->port = port; |
105 conn->addr = *addr; | 140 if (host != NULL) { |
106 | |
107 if (ptype == NN_PROXY_SOCKS4A && host == NULL) { | |
108 nn_conn_err(conn, "Host string NULL and proxy type SOCKS 4a specified. Using IP address instead.\n"); | |
109 conn->host = th_strdup(inet_ntoa(dest.sin_addr)); | |
110 } else | |
111 conn->host = th_strdup(host); | 141 conn->host = th_strdup(host); |
142 conn->hst = nn_resolve_host(conn, host); | |
143 } | |
144 | |
145 if (conn->hst != NULL) | |
146 conn->addr = *(struct in_addr *) (conn->hst->h_addr); | |
147 else { | |
148 conn->addr.s_addr = 0; | |
149 } | |
112 | 150 |
113 | 151 |
114 /* Prepare for connection */ | 152 /* Prepare for connection */ |
115 if (ptype > NN_PROXY_NONE && ptype < NN_PROXY_LAST) { | 153 if (conn->proxy.type > NN_PROXY_NONE && conn->proxy.type < NN_PROXY_LAST) { |
116 dest.sin_family = AF_INET; | 154 dest.sin_family = AF_INET; |
117 dest.sin_port = htons(pport); | 155 dest.sin_port = htons(conn->proxy.port); |
118 dest.sin_addr = conn->proxy.addr; | 156 dest.sin_addr = conn->proxy.addr; |
119 | 157 |
120 nn_conn_msg(conn, "Connecting to %s proxy %s:%d ...\n", | 158 nn_conn_msg(conn, "Connecting to %s proxy %s:%d ...\n", |
121 nn_proxy_types[ptype], | 159 nn_proxy_types[conn->proxy.type], |
122 inet_ntoa(dest.sin_addr), port); | 160 inet_ntoa(dest.sin_addr), port); |
123 } else { | 161 } else { |
124 dest.sin_family = AF_INET; | 162 dest.sin_family = AF_INET; |
125 dest.sin_port = htons(port); | 163 dest.sin_port = htons(port); |
126 dest.sin_addr = *addr; | 164 dest.sin_addr = conn->addr; |
127 | 165 |
128 nn_conn_msg(conn, "Connecting to %s:%d ...\n", | 166 nn_conn_msg(conn, "Connecting to %s:%d ...\n", |
129 inet_ntoa(dest.sin_addr), port); | 167 inet_ntoa(dest.sin_addr), port); |
130 } | 168 } |
131 | 169 |
145 | 183 |
146 FD_ZERO(&(conn->sockfds)); | 184 FD_ZERO(&(conn->sockfds)); |
147 FD_SET(conn->socket, &(conn->sockfds)); | 185 FD_SET(conn->socket, &(conn->sockfds)); |
148 | 186 |
149 /* Proxy-specific setup */ | 187 /* Proxy-specific setup */ |
150 if (ptype == NN_PROXY_SOCKS4 || ptype == NN_PROXY_SOCKS4A) { | 188 if (conn->proxy.type == NN_PROXY_SOCKS4 || conn->proxy.type == NN_PROXY_SOCKS4A) { |
151 struct nn_socks_t *socksh; | 189 struct nn_socks_t *socksh; |
152 size_t bufsiz = sizeof(struct nn_socks_t) + strlen(userid) + 1 + strlen(conn->host) + 1; | 190 size_t bufsiz = sizeof(struct nn_socks_t) + strlen(userid) + 1 + strlen(conn->host) + 1; |
153 char *ptr, *buf; | 191 char *ptr, *buf; |
154 int tries, status = -1; | 192 int tries, status = -1; |
155 | 193 |
161 } | 199 } |
162 | 200 |
163 /* Create SOCKS 4/4A request */ | 201 /* Create SOCKS 4/4A request */ |
164 nn_conn_msg(conn, "Initializing proxy negotiation.\n"); | 202 nn_conn_msg(conn, "Initializing proxy negotiation.\n"); |
165 socksh = (struct nn_socks_t *) buf; | 203 socksh = (struct nn_socks_t *) buf; |
166 socksh->version = (ptype == NN_PROXY_SOCKS4) ? 4 : 5; | 204 socksh->version = 4; |
167 socksh->command = SOCKS_CMD_CONNECT; | 205 socksh->command = SOCKS_CMD_CONNECT; |
168 socksh->port = htons(port); | 206 socksh->port = htons(port); |
169 if (ptype == NN_PROXY_SOCKS4A) | 207 if (conn->proxy.type == NN_PROXY_SOCKS4A) |
170 socksh->addr = htonl(0x00000032); | 208 socksh->addr = htonl(0x00000032); |
171 else | 209 else |
172 socksh->addr = dest.sin_addr.s_addr; | 210 socksh->addr = conn->addr.s_addr; |
173 ptr += sizeof(struct nn_socks_t); | 211 ptr += sizeof(struct nn_socks_t); |
174 | 212 |
175 strcpy(ptr, userid); | 213 strcpy(ptr, userid); |
176 ptr += strlen(userid) + 1; | 214 ptr += strlen(userid) + 1; |
177 | 215 |
213 else | 251 else |
214 goto error; | 252 goto error; |
215 } | 253 } |
216 | 254 |
217 conn->status = NN_CONN_OPEN; | 255 conn->status = NN_CONN_OPEN; |
218 return conn; | 256 return 0; |
219 | 257 |
220 error: | 258 error: |
221 conn->status = NN_CONN_CLOSED; | 259 conn->status = NN_CONN_CLOSED; |
222 return conn; | 260 return -2; |
223 } | 261 } |
224 | 262 |
225 | 263 |
226 void nn_conn_close(nn_conn_t *conn) | 264 void nn_conn_close(nn_conn_t *conn) |
227 { | 265 { |
234 #else | 272 #else |
235 close(conn->socket); | 273 close(conn->socket); |
236 #endif | 274 #endif |
237 conn->socket = -1; | 275 conn->socket = -1; |
238 } | 276 } |
239 | 277 |
278 th_free(conn->host); | |
279 th_free(conn->proxy.host); | |
280 | |
240 conn->status = NN_CONN_CLOSED; | 281 conn->status = NN_CONN_CLOSED; |
241 | 282 |
242 th_free(conn); | 283 th_free(conn); |
243 } | 284 } |
244 | 285 |