implemented server, client listener, socket tunnel and config reader

master
bvn13 2019-02-19 00:11:30 +03:00
parent ff32f3525b
commit b6eb1161af
6 changed files with 125 additions and 1 deletions

7
build.sbt 100644
View File

@ -0,0 +1,7 @@
name := "ScaProxy"
version := "0.1"
scalaVersion := "2.12.8"
libraryDependencies += "org.ekrich" %% "sconfig" % "0.7.0"

View File

@ -0,0 +1,2 @@
scaproxy.host = "localhost"
scaproxy.port = 9090

View File

@ -0,0 +1,14 @@
package ru.bvn13.scaproxy.config
import org.ekrich.config.{Config, ConfigFactory}
object Config {
private val config: Config = ConfigFactory.systemEnvironment()
.withFallback(ConfigFactory.parseResources("application.conf"))
def host:String = config.getString("scaproxy.host")
def port:Int = config.getInt("scaproxy.port")
}

View File

@ -0,0 +1,47 @@
package ru.bvn13.scaproxy.engine
import java.io.{BufferedReader, InputStreamReader}
import java.net.{InetAddress, Socket}
import java.util.concurrent.{ExecutorService, Executors}
import java.util.regex.{Matcher, Pattern}
case class ClientListener(clientSocket: Socket) extends Runnable {
private val RE_HOST = Pattern.compile("^Host: (\\S)+:(\\d)*")
private var buffer: List[String] = List()
private var outgoingTunnel: SocketTunnel = ???
private var incomingTunnel: SocketTunnel = ???
private val executorService: ExecutorService = Executors.newFixedThreadPool(2)
override def run(): Unit = {
val clientStream = new BufferedReader(new InputStreamReader(clientSocket.getInputStream))
var line = clientStream.readLine
while (line != null && !line.isEmpty) {
buffer = line :: buffer
}
if (buffer.length >= 2) {
val matcher: Matcher = RE_HOST.matcher(buffer(2))
if (matcher.matches) {
val host:String = matcher.group(1)
val port:String = if (matcher.groupCount > 2) matcher.group(2) else "80"
val remoteSocket: Socket = new Socket(InetAddress.getByName(host), port.toInt)
outgoingTunnel = SocketTunnel(sender = clientSocket, receiver = remoteSocket)
outgoingTunnel.initialBuffer = buffer
incomingTunnel = SocketTunnel(sender = remoteSocket, receiver = clientSocket)
executorService.execute(outgoingTunnel)
executorService.execute(incomingTunnel)
}
}
}
}

View File

@ -1,10 +1,44 @@
package ru.bvn13.scaproxy.engine
import java.io.IOException
import java.net.{InetAddress, ServerSocket, Socket}
import java.util.concurrent.{ExecutorService, Executors}
import ru.bvn13.scaproxy.config.Config
class ProxyServer {
def start = {
private val executorService: ExecutorService = Executors.newCachedThreadPool
private var clients: List[ClientListener] = List()
def start():Unit = {
println("ScaProxy started")
println("listening "+Config.host+":"+Config.port)
executorService.execute(mainThread)
}
def mainThread:Runnable = () => {
val serverSocket: ServerSocket = new ServerSocket(Config.port, 0, InetAddress.getByName(Config.host))
try {
while (!serverSocket.isClosed) {
val socket: Socket = serverSocket.accept()
val clientListener: ClientListener = ClientListener(socket)
executorService.execute(clientListener)
clients = clientListener :: clients
}
} catch {
case e: IOException => e.printStackTrace()
} finally {
serverSocket.close()
}
}

View File

@ -0,0 +1,20 @@
package ru.bvn13.scaproxy.engine
import java.io.{InputStreamReader, OutputStreamWriter}
import java.net.Socket
case class SocketTunnel(sender: Socket, receiver: Socket) extends Runnable {
private val senderStream: InputStreamReader = new InputStreamReader(sender.getInputStream)
private val receiverStream: OutputStreamWriter = new OutputStreamWriter(receiver.getOutputStream)
var initialBuffer: List[String] = List()
override def run(): Unit = {
}
}