Skip to content

Commit 16bf50c

Browse files
committed
Merge branch 'concurrent_tcp' into socks5-tcp
1 parent 4c6a86a commit 16bf50c

File tree

4 files changed

+158
-2
lines changed

4 files changed

+158
-2
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,5 +101,6 @@ tutorial/sockets/step4
101101
tutorial/sockets/step5
102102
tutorial/sockets/.dirstamp
103103
examples/.dirstamp
104+
examples/socks5proxy
104105
examples/webapp
105106
build/

Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ endif
200200

201201
if DILL_SOCKETS
202202
noinst_PROGRAMS += \
203+
examples/socks5proxy \
203204
examples/webapp
204205
endif
205206

examples/socks5proxy.c

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/*
2+
3+
Copyright (c) 2018 Joseph deBlaquiere
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"),
7+
to deal in the Software without restriction, including without limitation
8+
the rights to use, copy, modify, merge, publish, distribute, sublicense,
9+
and/or sell copies of the Software, and to permit persons to whom
10+
the Software is furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included
13+
in all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18+
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21+
IN THE SOFTWARE.
22+
23+
*/
24+
25+
#include "assert.h"
26+
#include "../libdill.h"
27+
#include <stdio.h>
28+
#include <string.h>
29+
30+
static char *auth_user = NULL;
31+
static char *auth_pass = NULL;
32+
33+
int auth_fn(const char *user, const char* pass) {
34+
if(auth_user) {
35+
if(!user) return 0;
36+
if(strcmp(user, auth_user) != 0) return 0;
37+
}
38+
if(auth_pass) {
39+
if(!pass) return 0;
40+
if(strcmp(pass, auth_pass) != 0) return 0;
41+
}
42+
return 1;
43+
}
44+
45+
// forwards input to output. return on error (connection closed)
46+
coroutine void forward(int in_s, int out_s, int ch) {
47+
while (1) {
48+
uint8_t d[1];
49+
int err = brecv(in_s, d, 1, -1);
50+
if (err) break ;
51+
err = bsend(out_s, d, 1, -1);
52+
if(err) break;
53+
}
54+
chdone(ch);
55+
return;
56+
}
57+
58+
coroutine void do_proxy(int s) {
59+
int err;
60+
if((!auth_user) || (!auth_pass)){
61+
err = socks5_proxy_auth(s, NULL, -1);
62+
} else {
63+
err = socks5_proxy_auth(s, auth_fn, -1);
64+
}
65+
if(err) goto in_close;
66+
67+
struct ipaddr addr;
68+
int cmd = socks5_proxy_recvcommand(s, &addr, -1);
69+
if(cmd != SOCKS5_CONNECT) goto in_close;
70+
71+
char addr_str[IPADDR_MAXSTRLEN];
72+
ipaddr_str(&addr, addr_str);
73+
74+
int s_rem = tcp_connect(&addr, -1);
75+
if(s_rem < 0) goto in_close;
76+
77+
err = ipaddr_remote(&addr, "0.0.0.0", 0, IPADDR_IPV4, -1);
78+
if(err) goto in_close;
79+
80+
err = socks5_proxy_sendreply(s, SOCKS5_SUCCESS, &addr, -1);
81+
if(err) goto in_close;
82+
83+
// channels for outboud, inbound to signal done (to close connection)
84+
int och[2], ich[2];
85+
err = chmake(och);
86+
if(err) goto both_close;
87+
err = chmake(ich);
88+
if(err) goto both_close;
89+
90+
int ob = go(forward(s, s_rem, och[1]));
91+
if(ob < 0) goto both_close;
92+
int ib = go(forward(s_rem, s, ich[1]));
93+
if(ib < 0) goto both_close;
94+
95+
struct chclause cc[] = {{CHRECV, och[0], &err, 1},
96+
{CHRECV, ich[0], &err, 1}};
97+
// wait for message in channel - one side closed
98+
int c = choose(cc, 2, -1);
99+
switch(c) {
100+
// one side closed, close the other
101+
case 0:
102+
err = bundle_wait(ob, -1);
103+
if(err) break;
104+
msleep(now()+100);
105+
hclose(ib);
106+
bundle_wait(ib, -1);
107+
break;
108+
case 1:
109+
err = bundle_wait(ib, -1);
110+
if(err) break;
111+
msleep(now()+100);
112+
hclose(ob);
113+
bundle_wait(ob, -1);
114+
break;
115+
case -1:
116+
// error
117+
break;
118+
default:
119+
// unexpected answer
120+
assert(0);
121+
}
122+
123+
both_close:
124+
tcp_close(s_rem, -1);
125+
in_close:
126+
tcp_close(s, -1);
127+
128+
return;
129+
}
130+
131+
int main(int argc, char** argv) {
132+
if (argc >=3) {
133+
// set up auth
134+
auth_user = argv[1];
135+
auth_pass = argv[2];
136+
}
137+
138+
int workers = bundle();
139+
struct ipaddr addr;
140+
int rc = ipaddr_local(&addr, NULL, 1080, 0);
141+
assert(rc == 0);
142+
int ls = tcp_listen(&addr, 10);
143+
assert(ls >= 0);
144+
printf("SOCKS5 proxy listening on :1080\n");
145+
while(1) {
146+
struct ipaddr caddr;
147+
int s = tcp_accept(ls, &caddr, -1);
148+
char caddr_str[IPADDR_MAXSTRLEN];
149+
ipaddr_str(&caddr, caddr_str);
150+
assert(s >= 0);
151+
rc = bundle_go(workers, do_proxy(s));
152+
assert(rc == 0);
153+
}
154+
}

tutorial/sockets/step5.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ int main(int argc, char *argv[]) {
128128
char name[256];
129129
char value[256];
130130
rc = http_recvfield(s, name, sizeof(name), value, sizeof(value), -1);
131-
if(rc == -1 && errno == EPIPE) break;
131+
if(rc == -1 && ((errno == EPIPE) || (ECONNRESET))) break;
132132
assert(rc == 0);
133133
fprintf(stderr, "%s: %s\n", name, value);
134134
}
@@ -140,7 +140,7 @@ int main(int argc, char *argv[]) {
140140
while(1) {
141141
unsigned char c;
142142
rc = brecv(s, &c, 1, -1);
143-
if(rc == -1 && errno == EPIPE) break;
143+
if(rc == -1 && ((errno == EPIPE) || (ECONNRESET))) break;
144144
fprintf(stdout, "%c", c);
145145
}
146146
fprintf(stderr, "\n");

0 commit comments

Comments
 (0)