@@ -11,23 +11,25 @@ class SocksCoroutineSocket(
11
11
val socksIsa : InetSocketAddress ,
12
12
channel : AsynchronousSocketChannel ,
13
13
val credentials : Pair <String , String >? = null ,
14
- readTimeout : Pair <Long , TimeUnit >? = null
14
+ readTimeout : Pair <Long , TimeUnit >? = null ,
15
15
) : CoroutineSocket(channel, readTimeout) {
16
16
17
17
enum class Method { NO_AUTH , USER_PASS }
18
18
19
19
enum class AddressType (val id : Byte ) {
20
20
IPv4 (0x01 .toByte()),
21
21
DOMAIN (0x03 .toByte()),
22
- IPv6 (0x04 .toByte());
22
+ IPv6 (0x04 .toByte()),
23
+ ;
23
24
24
25
private suspend fun sizeOfAddress (read : suspend (ByteBuffer ) -> Int ): Int = when (this ) {
25
26
IPv4 -> 0x04
26
27
IPv6 -> 0x10
27
28
DOMAIN -> ByteBuffer .allocate(1 ).let {
28
29
val count = read(it)
29
- if (count < 1 )
30
+ if (count < 1 ) {
30
31
throw SocksException (" failed to read domain name length for address. $count < 1" )
32
+ }
31
33
it[0 ].toUByte().toInt()
32
34
}
33
35
}
@@ -36,8 +38,9 @@ class SocksCoroutineSocket(
36
38
sizeOfAddress(read).let {
37
39
val buffer = ByteBuffer .allocate(it + 2 )
38
40
val count = read(buffer)
39
- if (count < it + 2 )
41
+ if (count < it + 2 ) {
40
42
throw SocksException (" failed to read address. $count < ${it + 2 } " )
43
+ }
41
44
buffer
42
45
}
43
46
}
@@ -51,16 +54,19 @@ class SocksCoroutineSocket(
51
54
val message = byteArrayOf(0x05 , methods.size.toByte(), * methods)
52
55
ByteBuffer .wrap(message).let {
53
56
val count = super .write(it)
54
- if (count < message.size)
57
+ if (count < message.size) {
55
58
throw SocksException (" failed to write methods message. $count < ${message.size} " )
59
+ }
56
60
}
57
61
58
62
val method = ByteBuffer .allocate(2 ).let {
59
63
val count = super .read(it)
60
- if (count < 2 )
64
+ if (count < 2 ) {
61
65
throw SocksException (" failed to read methods response. $count < 2" )
62
- if (it[0 ] != 0x05 .toByte())
66
+ }
67
+ if (it[0 ] != 0x05 .toByte()) {
63
68
throw SocksException (" methods response: versions mismatch: ${it[0 ]} " )
69
+ }
64
70
it[1 ]
65
71
}
66
72
return when (method) {
@@ -71,23 +77,32 @@ class SocksCoroutineSocket(
71
77
}
72
78
73
79
private suspend fun socksConnect (isa : InetSocketAddress ): InetSocketAddress {
74
- if (! this ::method.isInitialized)
80
+ if (! this ::method.isInitialized) {
75
81
throw IllegalStateException (" socks auth method is not initialized. maybe you forget to call init()?" )
76
- val message = byteArrayOf(0x05 , 0x01 , 0x00 , 0x01 ,
82
+ }
83
+ val message = byteArrayOf(
84
+ 0x05 ,
85
+ 0x01 ,
86
+ 0x00 ,
87
+ 0x01 ,
77
88
* isa.address.address,
78
89
(isa.port shr 8 ).toByte(),
79
- (isa.port and 0xff ).toByte())
90
+ (isa.port and 0xff ).toByte(),
91
+ )
80
92
ByteBuffer .wrap(message).let {
81
93
val count = super .write(it)
82
- if (count < message.size)
94
+ if (count < message.size) {
83
95
throw SocksException (" failed to write connect message. $count < ${message.size} " )
96
+ }
84
97
}
85
98
val header = ByteBuffer .allocate(4 ).also {
86
99
val count = super .read(it)
87
- if (count < 4 )
100
+ if (count < 4 ) {
88
101
throw SocksException (" failed to read header of connect response. $count < 4" )
89
- if (it[1 ] != 0x00 .toByte())
102
+ }
103
+ if (it[1 ] != 0x00 .toByte()) {
90
104
throw ConnectException (" failed to connect to ${isa.address.canonicalHostName} :${isa.port} . socks server respond ${it[1 ]} code" )
105
+ }
91
106
}
92
107
val addrType = AddressType .values().firstOrNull { it.id == header[3 ] }
93
108
? : throw SocksException (" unknown address type ${header[3 ]} " )
@@ -102,26 +117,36 @@ class SocksCoroutineSocket(
102
117
}
103
118
104
119
private suspend fun socksUserPassNegotiations () {
105
- if (credentials == null )
120
+ if (credentials == null ) {
106
121
throw SocksException (" server want to use user/pass authentication, but no credentials provided" )
122
+ }
107
123
val (username, password) = credentials
108
- if (username.length > 255 || password.length > 255 )
124
+ if (username.length > 255 || password.length > 255 ) {
109
125
throw SocksException (" credentials is invalid. max length of username and password is 255" )
110
- val message = byteArrayOf(0x01 , username.length.toByte(), * username.toByteArray(),
111
- password.length.toByte(), * password.toByteArray())
126
+ }
127
+ val message = byteArrayOf(
128
+ 0x01 ,
129
+ username.length.toByte(),
130
+ * username.toByteArray(),
131
+ password.length.toByte(),
132
+ * password.toByteArray(),
133
+ )
112
134
ByteBuffer .wrap(message).also {
113
135
val count = super .write(it)
114
- if (count < message.size)
136
+ if (count < message.size) {
115
137
throw SocksException (" failed to write user/pass message. $count < ${message.size} " )
138
+ }
116
139
}
117
140
val response = ByteBuffer .allocate(2 ).let {
118
141
val count = super .read(it)
119
- if (count < 2 )
142
+ if (count < 2 ) {
120
143
throw SocksException (" failed to read user/pass response. $count < 2" )
144
+ }
121
145
it[1 ]
122
146
}
123
- if (response != 0x00 .toByte())
147
+ if (response != 0x00 .toByte()) {
124
148
throw SocksException (" authentication failure. server respond $response != 0x00" )
149
+ }
125
150
}
126
151
127
152
lateinit var method: Method
@@ -163,18 +188,20 @@ class SocksCoroutineSocket(
163
188
}
164
189
165
190
override suspend fun read (buffer : ByteBuffer ): Int {
166
- if (! this ::remoteIsa.isInitialized)
191
+ if (! this ::remoteIsa.isInitialized) {
167
192
throw IllegalStateException (" remote address is not initialized. please, connect first" )
193
+ }
168
194
return super .read(buffer).also {
169
195
if (it < 0 ) close()
170
196
}
171
197
}
172
198
173
199
override suspend fun write (buffer : ByteBuffer ): Int {
174
- if (! this ::remoteIsa.isInitialized)
200
+ if (! this ::remoteIsa.isInitialized) {
175
201
throw IllegalStateException (" remote address is not initialized. please, connect first" )
202
+ }
176
203
return super .write(buffer).also {
177
204
if (it < 0 ) close()
178
205
}
179
206
}
180
- }
207
+ }
0 commit comments