Communicate with `lightningd` to tell it about our options, RPC methods and subscribe to hooks, and then process the initialization, configuring the plugin. Returns `None` if we were invoked with `--help` and thus should exit after this handshake
(mut self)
| 205 | /// Returns `None` if we were invoked with `--help` and thus |
| 206 | /// should exit after this handshake |
| 207 | pub async fn configure(mut self) -> Result<Option<ConfiguredPlugin<S, I, O>>, anyhow::Error> { |
| 208 | let mut input = FramedRead::new(self.input.take().unwrap(), JsonRpcCodec::default()); |
| 209 | |
| 210 | // Sadly we need to wrap the output in a mutex in order to |
| 211 | // enable early logging, i.e., logging that is done before the |
| 212 | // PluginDriver is processing events during the |
| 213 | // handshake. Otherwise we could just write the log events to |
| 214 | // the event queue and have the PluginDriver be the sole owner |
| 215 | // of `Stdout`. |
| 216 | let output = Arc::new(Mutex::new(FramedWrite::new( |
| 217 | self.output.take().unwrap(), |
| 218 | JsonCodec::default(), |
| 219 | ))); |
| 220 | |
| 221 | // Now configure the logging, so any `log` call is wrapped |
| 222 | // in a JSON-RPC notification and sent to Core Lightning |
| 223 | crate::logging::init(output.clone()).await?; |
| 224 | trace!("Plugin logging initialized"); |
| 225 | |
| 226 | // Read the `getmanifest` message: |
| 227 | match input.next().await { |
| 228 | Some(Ok(messages::JsonRpc::Request(id, messages::Request::Getmanifest(m)))) => { |
| 229 | output |
| 230 | .lock() |
| 231 | .await |
| 232 | .send(json!({ |
| 233 | "jsonrpc": "2.0", |
| 234 | "result": self.handle_get_manifest(m), |
| 235 | "id": id, |
| 236 | })) |
| 237 | .await? |
| 238 | } |
| 239 | Some(o) => return Err(anyhow!("Got unexpected message {:?} from lightningd", o)), |
| 240 | None => { |
| 241 | return Err(anyhow!( |
| 242 | "Lost connection to lightning expecting getmanifest" |
| 243 | )) |
| 244 | } |
| 245 | }; |
| 246 | let (init_id, configuration) = match input.next().await { |
| 247 | Some(Ok(messages::JsonRpc::Request(id, messages::Request::Init(m)))) => { |
| 248 | (id, self.handle_init(m)?) |
| 249 | } |
| 250 | |
| 251 | Some(o) => return Err(anyhow!("Got unexpected message {:?} from lightningd", o)), |
| 252 | None => { |
| 253 | // If we are being called with --help we will get |
| 254 | // disconnected here. That's expected, so don't |
| 255 | // complain about it. |
| 256 | return Ok(None); |
| 257 | } |
| 258 | }; |
| 259 | |
| 260 | // TODO Split the two hashmaps once we fill in the hook |
| 261 | // payload structs in messages.rs |
| 262 | let mut rpcmethods: HashMap<String, AsyncCallback<S>> = |
| 263 | HashMap::from_iter(self.rpcmethods.drain().map(|(k, v)| (k, v.callback))); |
| 264 | rpcmethods.extend(self.hooks.drain().map(|(k, v)| (k, v.callback))); |