Skip to content

Commit

Permalink
editing ch05
Browse files Browse the repository at this point in the history
  • Loading branch information
spamegg1 committed Apr 7, 2024
1 parent a1c7f1a commit 0c303ac
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 59 deletions.
9 changes: 3 additions & 6 deletions src/main/scala/ch04/00common.scala
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package ch04.common

import scalanative.unsigned.UnsignedRichInt // .toUSize
import scalanative.unsigned.{USize, UnsignedRichInt} // .toUSize
import scalanative.unsafe.{CQuote, toCString, Ptr, CString}
import scalanative.unsafe.{Zone, stackalloc, sizeof, extern}
import scalanative.libc.{stdlib, string, stdio, errno}
import scalanative.posix.unistd // getpid
import scala.scalanative.unsigned.USize

// This is a "conceptual" Scala version of execve
case class Command(path: String, args: String, env: Map[String, String])
Expand All @@ -26,11 +25,9 @@ def await(pid: Int): Int =
util.waitpid(pid, status, 0)
val statusCode = !status
if statusCode != 0 then throw Exception(s"Child process returned error $statusCode")
!status
statusCode

def doAndAwait(task: Function0[Int]): Int =
val pid = doFork(task)
await(pid)
def doAndAwait(task: Function0[Int]): Int = await(doFork(task))

def runCommand(args: Seq[String], env: Map[String, String] = Map.empty): Int =
if args.size == 0 then throw Exception("bad arguments of length 0")
Expand Down
3 changes: 1 addition & 2 deletions src/main/scala/ch05/acceptExample
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package `05acceptExample`
package ch05.examples.accept

import scalanative.unsafe.*
import scalanative.unsigned.*
import scalanative.libc.*
// import scalanative.native.*
import stdio.*, string.*, stdlib.*
import scalanative.posix.unistd.*
import scalanative.posix.sys.socket.*
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/ch05/bindExample
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package `05bindExample`
package ch05.examples.bind

import scalanative.unsafe.*
import scalanative.unsigned.*
Expand Down
4 changes: 1 addition & 3 deletions src/main/scala/ch05/blockingServer
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package ch05.blockingServer
import scalanative.unsafe.*
import scalanative.unsigned.*
import scalanative.libc.*
// import scalanative.native.*
import stdio.*, string.*, stdlib.*
import scalanative.posix.unistd.*
import scalanative.posix.sys.socket.*
Expand Down Expand Up @@ -49,8 +48,7 @@ def handleConnection(connSocket: Int, maxSize: Int = 1024): Unit =
val bytesRead = read(connSocket, lineBuffer, maxSize)
println(s"read $bytesRead bytes")

// This means the connection has been closed by the client
if bytesRead == EOF then break()
if bytesRead == EOF then break() // connection has been closed by the client

val bytesWritten = write(connSocket, lineBuffer, bytesRead)
println(s"wrote $bytesWritten bytes")
79 changes: 32 additions & 47 deletions src/main/scala/ch05/httpserver/HTTPServer.scala
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
package ch05.httpServer

import scalanative.unsigned.{UnsignedRichInt, UInt, UShort}
import scalanative.unsafe.*
import scalanative.libc.*
import stdio.{FILE, fclose}
import stdlib.malloc
import scalanative.posix.unistd.*
import scalanative.posix.sys.socket.*
import scalanative.posix.netinet.in.*
import scalanative.posix.arpa.inet.*
import collection.mutable
import scalanative.unsafe.{CString, CQuote, stackalloc, sizeof, fromCString, toCString}
import scalanative.unsafe.{Ptr, extern, Zone}
import scalanative.libc.{stdio, stdlib, string, errno}, stdio.FILE, stdlib.malloc
import scalanative.posix.unistd
import scalanative.posix.sys.socket, socket.{sockaddr, AF_INET, SOCK_STREAM}
import scalanative.posix.netinet.in.{sockaddr_in, INADDR_ANY}
import scalanative.posix.arpa.inet

case class HttpRequest(
method: String,
uri: String,
headers: collection.Map[String, String],
body: String
)

case class HttpResponse(
code: Int,
headers: collection.Map[String, String],
Expand All @@ -40,29 +37,21 @@ object Parsing:
val methodBuffer = stackalloc[Byte](16)
val urlBuffer = stackalloc[Byte](1024)
val protocolBuffer = stackalloc[Byte](32)
val scanResult = stdio.sscanf(
line,
c"%s %s %s\n",
methodBuffer,
urlBuffer,
protocolBuffer
)
val scanResult =
stdio.sscanf(line, c"%s %s %s\n", methodBuffer, urlBuffer, protocolBuffer)
if scanResult < 3 then throw Exception("bad request line")
else
val method = fromCString(methodBuffer)
val url = fromCString(urlBuffer)
(method, url)
else (fromCString(methodBuffer), fromCString(urlBuffer))

def parseRequest(conn: Int): Option[HttpRequest] =
val socketFd = util.fdopen(conn, c"r")
val lineBuffer = stdlib.malloc(4096.toUSize) // fix // 0.5
val lineBuffer = stdlib.malloc(4096) // fix // 0.5
var readResult = stdio.fgets(lineBuffer, 4096, socketFd)

val (method, url) = parseRequestLine(lineBuffer)
stdio.printf(c"read request line: %s", lineBuffer)
println(s"${(method, url)}")

var headers = mutable.Map[String, String]()
var headers = collection.mutable.Map[String, String]()
readResult = stdio.fgets(lineBuffer, 4096, socketFd)

var lineLength = string.strlen(lineBuffer)
Expand All @@ -76,45 +65,46 @@ object Parsing:

def writeResponse(conn: Int, resp: HttpResponse): Unit =
val socketFd = util.fdopen(conn, c"r+")
Zone { // implicit z => // 0.5
Zone: // implicit z => // 0.5
stdio.fprintf(socketFd, c"%s %s %s\r\n", c"HTTP/1.1", c"200", c"OK")

for (k, v) <- resp.headers
do stdio.fprintf(socketFd, c"%s: %s\r\n", toCString(k), toCString(v))

stdio.fprintf(socketFd, c"\r\n")
stdio.fprintf(socketFd, toCString(resp.body))
}
fclose(socketFd)

stdio.fclose(socketFd)

@main
def httpServer05(args: String*): Unit = serve(8082.toUShort)
def httpServer05: Unit = serve(8082.toUShort)

def serve(port: UShort): Unit =
// Allocate and initialize the server address
val addrSize = sizeof[sockaddr_in]
val serverAddress = malloc(addrSize).asInstanceOf[Ptr[sockaddr_in]]
serverAddress._1 = AF_INET.toUShort // IP Socket
serverAddress._2 = htons(port) // port
serverAddress._3._1 = htonl(INADDR_ANY) // bind to 0.0.0.0
serverAddress._2 = inet.htons(port) // port
serverAddress._3._1 = inet.htonl(INADDR_ANY) // bind to 0.0.0.0

// Bind and listen on a socket
val sockFd = socket(AF_INET, SOCK_STREAM, 0)
val sockFd = socket.socket(AF_INET, SOCK_STREAM, 0)
val serverSockAddr = serverAddress.asInstanceOf[Ptr[sockaddr]]
val bindResult = bind(sockFd, serverSockAddr, addrSize.toUInt)

val bindResult = socket.bind(sockFd, serverSockAddr, addrSize.toUInt)
println(s"bind returned $bindResult")
val listenResult = listen(sockFd, 128)

val listenResult = socket.listen(sockFd, 128)
println(s"listen returned $listenResult")

val incoming = malloc(sizeof[sockaddr_in]).asInstanceOf[Ptr[sockaddr]]
val incSz = malloc(sizeof[UInt]).asInstanceOf[Ptr[UInt]]
!incSz = sizeof[sockaddr_in].toUInt
println(s"accepting connections on port $port")

// Main accept() loop
while true do
while true do // Main accept() loop
println(s"accepting")
val connectionFd = accept(sockFd, incoming, incSz)
val connectionFd = socket.accept(sockFd, incoming, incSz)
println(s"accept returned fd $connectionFd")

if connectionFd <= 0 then
Expand All @@ -124,21 +114,16 @@ def serve(port: UShort): Unit =

// we will replace handleConnection with fork_and_handle shortly
handleConnection(connectionFd)
close(connectionFd)

close(sockFd)
unistd.close(connectionFd)

import Parsing.*, scala.util.boundary, boundary.break
unistd.close(sockFd)

def handleConnection(connSocket: Int, maxSize: Int = 1024): Unit =
boundary:
while true do
parseRequest(connSocket) match
case Some(request) =>
val response = handleRequest(request)
writeResponse(connSocket, response)
break() // replaced return
case None => break() // replaced return
Parsing.parseRequest(connSocket) match
case Some(request) =>
val response = handleRequest(request)
Parsing.writeResponse(connSocket, response)
case None => ()

def handleRequest(request: HttpRequest): HttpResponse =
val headers = Map("Content-type" -> "text/html")
Expand Down

0 comments on commit 0c303ac

Please sign in to comment.