quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

TalerWalletCore.kt (8231B)


      1 /*
      2  * This file is part of GNU Taler
      3  * (C) 2023 Taler Systems S.A.
      4  *
      5  * GNU Taler is free software; you can redistribute it and/or modify it under the
      6  * terms of the GNU General Public License as published by the Free Software
      7  * Foundation; either version 3, or (at your option) any later version.
      8  *
      9  * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
     10  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11  * A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU General Public License along with
     14  * GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15  */
     16 
     17 /*
     18  * This file is part of GNU Taler
     19  * (C) 2023 Taler Systems S.A.
     20  *
     21  * GNU Taler is free software; you can redistribute it and/or modify it under the
     22  * terms of the GNU General Public License as published by the Free Software
     23  * Foundation; either version 3, or (at your option) any later version.
     24  *
     25  * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
     26  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     27  * A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     28  *
     29  * You should have received a copy of the GNU General Public License along with
     30  * GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     31  */
     32 
     33 package net.taler.qtart
     34 
     35 import com.sun.jna.Callback
     36 import com.sun.jna.Library
     37 import com.sun.jna.Native
     38 import com.sun.jna.Pointer
     39 import com.sun.jna.Structure
     40 
     41 class TalerWalletCore {
     42     internal interface TalerNative : Library {
     43         companion object {
     44             val INSTANCE: TalerNative by lazy {
     45                 Native.setProtected(true)
     46                 Native.load("talerwalletcore", TalerNative::class.java)
     47             }
     48         }
     49 
     50         interface TALER_WALLET_MessageHandlerFn : Callback {
     51             fun invoke(handler_p: Pointer, message: String)
     52         }
     53 
     54         interface TALER_LogFn : Callback {
     55             fun invoke(cls: Pointer, stream: Int, msg: String)
     56         }
     57 
     58         fun TALER_WALLET_create(): Pointer
     59         fun TALER_WALLET_set_message_handler(
     60             twi: Pointer,
     61             handler_f: TALER_WALLET_MessageHandlerFn,
     62             handler_p: Pointer
     63         )
     64 
     65         fun TALER_WALLET_send_request(twi: Pointer, request: String): Int
     66         fun TALER_WALLET_run(twi: Pointer): Int
     67         fun TALER_WALLET_join(twi: Pointer)
     68         fun TALER_WALLET_destroy(twi: Pointer)
     69         fun TALER_start_redirect_std(logfn: TALER_LogFn, cls: Pointer)
     70         fun TALER_set_curl_http_client(twi: Pointer)
     71 
     72         /**
     73          * Native networking
     74          */
     75 
     76         class JSHttpRequestInfo: Structure() {
     77             @JvmField var response_cb: JSHttpResponseCb? = null
     78             @JvmField var response_cb_cls: Pointer? = null
     79             @JvmField var url: String? = null
     80             @JvmField var method: String? = null
     81             @JvmField var request_headers: Pointer? = null // Array<String>
     82             @JvmField var redirect: Int? = null
     83             @JvmField var timeout_ms: Int? = null
     84             @JvmField var debug: Int? = null
     85             @JvmField var req_body: Pointer? = null // ByteArray
     86             @JvmField var req_body_len: Int? = null
     87 
     88             override fun getFieldOrder() = mutableListOf(
     89                 "response_cb",
     90                 "response_cb_cls",
     91                 "url",
     92                 "method",
     93                 "request_headers",
     94                 "redirect",
     95                 "timeout_ms",
     96                 "debug",
     97                 "req_body",
     98                 "req_body_len",
     99             )
    100         }
    101 
    102         class JSHttpResponseInfo: Structure() {
    103             @JvmField var request_id: Int? = null
    104             @JvmField var status: Int? = null
    105             @JvmField var errmsg: String? = null
    106             @JvmField var response_headers: Pointer? = null
    107             @JvmField var num_response_headers: Int? = null
    108             @JvmField var body: Pointer? = null
    109             @JvmField var body_len: Int? = null
    110 
    111             override fun getFieldOrder() = mutableListOf(
    112                 "request_id",
    113                 "status",
    114                 "errmsg",
    115                 "response_headers",
    116                 "num_response_headers",
    117                 "body",
    118                 "body_len",
    119             )
    120         }
    121 
    122         interface JSHttpResponseCb: Callback {
    123             fun invoke(cls: Pointer, resp: JSHttpResponseInfo)
    124         }
    125 
    126         interface JSHttpRequestCb: Callback {
    127             fun invoke(cls: Pointer, req_info: JSHttpRequestInfo)
    128         }
    129 
    130         interface JSHttpReqCreateFn: Callback {
    131             fun invoke(cls: Pointer, req_info: JSHttpRequestInfo): Int
    132         }
    133 
    134         interface JSHttpReqCancelFn: Callback {
    135             fun invoke(cls: Pointer, request_id: Int): Int
    136         }
    137 
    138         fun TALER_set_http_client_implementation(twi: Pointer, impl: Pointer)
    139 
    140         fun TALER_pack_http_client_implementation(
    141             req_create: JSHttpReqCreateFn,
    142             req_cancel: JSHttpReqCancelFn,
    143             handler_p: Pointer,
    144         ): Pointer
    145     }
    146 
    147     private val walletInstance: Pointer = TalerNative.INSTANCE.TALER_WALLET_create()
    148 
    149     // Handlers must be here, so that GC doesn't wipe them!
    150     // Please don't refactor them, or else you'll suffer!
    151     private var currentMessageHandler: TalerNative.TALER_WALLET_MessageHandlerFn? = null
    152     private var currentLogHandler: TalerNative.TALER_LogFn? = null
    153     private var currentReqCreateHandler: TalerNative.JSHttpReqCreateFn? = null
    154     private var currentReqCancelHandler: TalerNative.JSHttpReqCancelFn? = null
    155     private var currentResHandler: TalerNative.JSHttpResponseCb? = null
    156 
    157     fun setMessageHandler(handler: (msg: String) -> Unit) {
    158         this.currentMessageHandler = object : TalerNative.TALER_WALLET_MessageHandlerFn {
    159             override fun invoke(handler_p: Pointer, message: String) {
    160                 handler(message)
    161             }
    162         }
    163         TalerNative.INSTANCE.TALER_WALLET_set_message_handler(
    164             walletInstance,
    165             this.currentMessageHandler!!,
    166             walletInstance
    167         )
    168     }
    169 
    170     fun setStdoutHandler(handler: (msg: String) -> Unit) {
    171         this.currentLogHandler = object : TalerNative.TALER_LogFn {
    172             override fun invoke(cls: Pointer, stream: Int, msg: String) {
    173                 handler(msg)
    174             }
    175         }
    176         TalerNative.INSTANCE.TALER_start_redirect_std(this.currentLogHandler!!, walletInstance)
    177     }
    178 
    179     fun sendRequest(request: String) {
    180         TalerNative.INSTANCE.TALER_WALLET_send_request(walletInstance, request)
    181     }
    182 
    183     fun setCurlHttpClient() {
    184         TalerNative.INSTANCE.TALER_set_curl_http_client(walletInstance)
    185     }
    186 
    187     fun run() {
    188         TalerNative.INSTANCE.TALER_WALLET_run(walletInstance)
    189     }
    190 
    191     fun destroy() {
    192         TalerNative.INSTANCE.TALER_WALLET_destroy(walletInstance)
    193     }
    194 
    195     fun join() {
    196         TalerNative.INSTANCE.TALER_WALLET_join(walletInstance)
    197     }
    198 
    199     /**
    200      * Native networking
    201      */
    202 
    203     fun setHttpClient(handler: Networking.RequestHandler) {
    204         this.currentReqCreateHandler = object: TalerNative.JSHttpReqCreateFn {
    205             override fun invoke(cls: Pointer, req_info: TalerNative.JSHttpRequestInfo): Int {
    206                 // TODO: return positive request_id on success, negative on failure
    207                 //  right now, this can't be done synchronously; doing it async
    208                 //  might require a modification in the C API.
    209                 return Networking.httpCreateRequest(req_info, handler)
    210             }
    211         }
    212         this.currentReqCancelHandler = object: TalerNative.JSHttpReqCancelFn {
    213             override fun invoke(cls: Pointer, request_id: Int): Int {
    214                 return Networking.httpCancelRequest(request_id, handler)
    215             }
    216         }
    217 
    218         val client = TalerNative.INSTANCE.TALER_pack_http_client_implementation(
    219             this.currentReqCreateHandler!!,
    220             this.currentReqCancelHandler!!,
    221             this.walletInstance,
    222         )
    223 
    224         TalerNative.INSTANCE.TALER_set_http_client_implementation(walletInstance, client)
    225     }
    226 }