diff options
Diffstat (limited to 'common/native')
-rw-r--r-- | common/native/src/main/scala/http/ArrayUtils.scala | 28 | ||||
-rw-r--r-- | common/native/src/main/scala/http/CurlBackend.scala | 215 | ||||
-rw-r--r-- | common/native/src/main/scala/http/curl.scala | 82 | ||||
-rw-r--r-- | common/native/src/main/scala/http/package.scala | 3 |
4 files changed, 0 insertions, 328 deletions
diff --git a/common/native/src/main/scala/http/ArrayUtils.scala b/common/native/src/main/scala/http/ArrayUtils.scala deleted file mode 100644 index 00c1067..0000000 --- a/common/native/src/main/scala/http/ArrayUtils.scala +++ /dev/null @@ -1,28 +0,0 @@ -package triad -package http - -import scala.scalanative.native._ - -object ArrayUtils { - - def toBuffer(array: Array[Byte])(implicit z: Zone): Ptr[Byte] = { - val buffer = z.alloc(array.size) - var i = 0 - while (i < array.size) { - buffer(i) = array(i) - i += 1 - } - buffer - } - - def toArray(buffer: Ptr[Byte], size: CSize): Array[Byte] = { - val array = new Array[Byte](size.toInt) - var i = 0 - while (i < array.size) { - array(i) = buffer(i) - i += 1 - } - array - } - -} diff --git a/common/native/src/main/scala/http/CurlBackend.scala b/common/native/src/main/scala/http/CurlBackend.scala deleted file mode 100644 index 4dc8577..0000000 --- a/common/native/src/main/scala/http/CurlBackend.scala +++ /dev/null @@ -1,215 +0,0 @@ -package triad -package http - -import curl._ -import curlh._ - -import scala.collection.{Map, mutable} -import scala.collection.mutable.ArrayBuffer -import scala.concurrent.Future -import scala.scalanative.native._ -import scala.util.{Failure, Success, Try} - -object CurlBackend { - - type Chunk = CStruct4[Ptr[CStruct0], Ptr[CStruct0], CSize, Ptr[Byte]] - implicit class ChunksOps(val self: Ptr[Chunk]) extends AnyVal { - @inline def prev: Ptr[Chunk] = (!self._1).cast[Ptr[Chunk]] - @inline def prev_=(other: Ptr[Chunk]): Unit = - !(self._1) = other.cast[Ptr[CStruct0]] - @inline def next: Ptr[Chunk] = (!self._2).cast[Ptr[Chunk]] - @inline def next_=(other: Ptr[Chunk]): Unit = - !(self._2) = other.cast[Ptr[CStruct0]] - @inline def size: CSize = !(self._3) - @inline def size_=(value: CSize): Unit = !(self._3) = value - @inline def buffer: Ptr[Byte] = !(self._4) - @inline def buffer_=(value: Ptr[Byte]): Unit = !(self._4) = value - } - - object Chunk { - - @inline def NullPtr[T] = 0.cast[Ptr[T]] - - def allocHead() = allocAppend(0, NullPtr[Chunk]) - - def allocAppend(size: CSize, - head: Ptr[Chunk] = NullPtr[Chunk]): Ptr[Chunk] = { - val chunk: Ptr[Chunk] = stdlib.malloc(sizeof[Chunk]).cast[Ptr[Chunk]] - if (chunk == NullPtr[Chunk]) return NullPtr[Chunk] - - chunk.buffer = stdlib.malloc(size) - - if (chunk.buffer == NullPtr[Chunk] && size != 0) { - stdlib.free(chunk.cast[Ptr[Byte]]) - return NullPtr[Chunk] - } - chunk.size = size - - if (head == NullPtr[Chunk]) { // this will be the head - chunk.next = chunk - chunk.prev = chunk - } else { - val last = head.prev - last.next = chunk - chunk.prev = last - head.prev = chunk - chunk.next = head - } - chunk - } - - def freeAll(head: Ptr[Chunk]): Unit = { - var chunk: Ptr[Chunk] = head - do { - val next = chunk.next - stdlib.free(chunk.buffer) - stdlib.free(chunk.cast[Ptr[Byte]]) - chunk = next - } while (chunk != head) - } - - def toArray(head: Ptr[Chunk]): Array[Byte] = { - val buffer = new ArrayBuffer[Byte]() - var chunk = head - do { - val next = chunk.next - var i = 0l - while (i < next.size) { - buffer += next.buffer(i) - i += 1 - } - chunk = next - } while (chunk != head) - buffer.toArray - } - - def traverse(head: Ptr[Chunk])(fct: Array[Byte] => Unit) = { - var chunk = head - do { - val next = chunk.next - val buffer = new ArrayBuffer[Byte]() - var i = 0l - while (i < next.size) { - buffer += next.buffer(i) - i += 1 - } - chunk = next - fct(buffer.toArray) - } while (chunk != head) - } - - } - - private def receive(data: Ptr[Byte], - size: CSize, - nmemb: CSize, - userdata: Ptr[Byte]): CSize = { - val head = userdata.cast[Ptr[Chunk]] - val length = size * nmemb - val chunk = Chunk.allocAppend(length, head) - string.memcpy(chunk.buffer, data, chunk.size) - chunk.size - } - private val receivePtr: WriteFunction = CFunctionPtr.fromFunction4(receive) - - private def chain[A](success: A)(calls: (() => A)*) = { - var result: A = success - for (c <- calls if result == success) { - result = c() - } - result - } - - private def request(request: Request)(implicit z: Zone): Try[Response] = { - val curl: CURL = curl_easy_init() - if (curl != null) { - val errorBuffer = stackalloc[Byte](CURL_ERROR_SIZE) - !errorBuffer = 0 - val requestHeaders = stackalloc[curl_slist](1) - !requestHeaders = 0.cast[curl_slist] - - val responseChunks = Chunk.allocHead() - val responseHeaderChunks = Chunk.allocHead() - - val curlResult = chain(CURLcode.CURL_OK)( - () => - curl_easy_setopt(curl, CURLoption.CURLOPT_ERRORBUFFER, errorBuffer), - () => - curl_easy_setopt(curl, - CURLoption.CURLOPT_CUSTOMREQUEST, - toCString(request.method)), - () => - curl_easy_setopt(curl, - CURLoption.CURLOPT_URL, - toCString(request.url)), - () => { - val buffer = ArrayUtils.toBuffer(request.body) - curl_easy_setopt(curl, CURLoption.CURLOPT_POSTFIELDS, buffer) - curl_easy_setopt(curl, - CURLoption.CURLOPT_POSTFIELDSIZE, - request.body.size) - }, - () => { - for ((k, v) <- request.headers) { - !requestHeaders = - curl_slist_append(!requestHeaders, toCString(s"$k:$v")) - } - curl_easy_setopt(curl, CURLoption.CURLOPT_HTTPHEADER, !requestHeaders) - }, - () => - curl_easy_setopt(curl, CURLoption.CURLOPT_WRITEFUNCTION, receivePtr), - () => - curl_easy_setopt(curl, CURLoption.CURLOPT_WRITEDATA, responseChunks), - () => - curl_easy_setopt(curl, - CURLoption.CURLOPT_HEADERDATA, - responseHeaderChunks), - () => curl_easy_perform(curl) - ) - - val result = curlResult match { - case CURLcode.CURL_OK => - val responseCode: Ptr[Long] = stackalloc[Long](1) - curl_easy_getinfo(curl, CURLINFO.CURLINFO_RESPONSE_CODE, responseCode) - - val responseHeaders = mutable.HashMap.empty[String, String] - Chunk.traverse(responseHeaderChunks) { headerChunk => - val line = new String(headerChunk, "utf-8").trim - if (line.contains(":")) { - val parts = line.split(":", 2) - responseHeaders += parts(0) -> parts(1) - } - } - - Success( - Response( - statusCode = (!responseCode).toInt, - headers = responseHeaders.toMap, - body = Chunk.toArray(responseChunks) - )) - - case code => - val message = curl_easy_strerror(curl, code) - Failure( - new RuntimeException( - s"${fromCString(errorBuffer)} (curl exit status $code)")) - } - Chunk.freeAll(responseChunks) - Chunk.freeAll(responseHeaderChunks) - curl_slist_free_all(!requestHeaders) - curl_easy_cleanup(curl) - result - } else { - Failure(new RuntimeException(s"curl failed to initialize")) - } - } - - def curlVersion = fromCString(curl_version()) - -} - -trait CurlBackend extends Backend { - def send(req: Request): Future[Response] = Zone { implicit z => - Future.fromTry(CurlBackend.request(req)) - } -} diff --git a/common/native/src/main/scala/http/curl.scala b/common/native/src/main/scala/http/curl.scala deleted file mode 100644 index 1eda584..0000000 --- a/common/native/src/main/scala/http/curl.scala +++ /dev/null @@ -1,82 +0,0 @@ -package triad -package http - -import scala.scalanative.native._ - -object curlh { - final val CURL_ERROR_SIZE = 256 - - type CURL = Ptr[CStruct0] - - /* - * #define CURLOPTTYPE_LONG 0 - * #define CURLOPTTYPE_OBJECTPOINT 10000 - * #define CURLOPTTYPE_STRINGPOINT 10000 - * #define CURLOPTTYPE_FUNCTIONPOINT 20000 - * #define CURLOPTTYPE_OFF_T 30000 - */ - - type CURLcode = CInt - object CURLcode { - final val CURL_OK: CInt = 0 - } - - type CURLoption = CInt - object CURLoption { - final val CURLOPT_VERBOSE: CInt = 41 - final val CURLOPT_POSTFIELDSIZE: CInt = 60 - final val CURLOPT_WRITEDATA: CInt = 10001 - final val CURLOPT_URL: CInt = 10002 - final val CURLOPT_ERRORBUFFER: CInt = 10010 - final val CURLOPT_POSTFIELDS: CInt = 10015 - final val CURLOPT_HTTPHEADER: CInt = 10023 - final val CURLOPT_HEADERDATA: CInt = 10029 - final val CURLOPT_CUSTOMREQUEST: CInt = 10036 - final val CURLOPT_WRITEFUNCTION: CInt = 20011 - } - - type CURLINFO = CInt - object CURLINFO { - final val CURLINFO_RESPONSE_CODE = 0x200002 - } - - type WriteFunction = CFunctionPtr4[ - Ptr[Byte], // data - CSize, // size - CSize, // nmemb - Ptr[Byte], // userdata - CSize // return - ] - - type curl_slist = Ptr[CStruct0] - -} - -@link("curl") -@extern -object curl { - import curlh._ - - def curl_easy_init(): CURL = extern - - def curl_easy_setopt(curl: CURL, - option: CURLoption, - parameter: CVararg*): CURLcode = extern - - def curl_easy_perform(curl: CURL): CURLcode = extern - - def curl_easy_getinfo(curl: CURL, - option: CURLINFO, - parameter: CVararg*): CURLcode = extern - - def curl_easy_cleanup(curl: CURL): Unit = extern - - def curl_easy_strerror(curl: CURL, code: CURLcode): CString = extern - - def curl_slist_append(head: curl_slist, string: CString): curl_slist = extern - - def curl_slist_free_all(head: curl_slist): Unit = extern - - def curl_version(): CString = extern - -} diff --git a/common/native/src/main/scala/http/package.scala b/common/native/src/main/scala/http/package.scala deleted file mode 100644 index 63b5405..0000000 --- a/common/native/src/main/scala/http/package.scala +++ /dev/null @@ -1,3 +0,0 @@ -package triad - -package object http extends CurlBackend |