@@ -10,16 +10,16 @@ use http_body_util::{BodyExt, Empty, Full};
1010use hyper:: body:: { Body , Bytes } ;
1111use hyper:: header:: { HeaderValue , ACCESS_CONTROL_ALLOW_ORIGIN , CONTENT_TYPE } ;
1212use hyper:: server:: conn:: http1;
13- use hyper:: { Method , Request , Response , StatusCode , Uri } ;
13+ use hyper:: { Method , Request , Response , StatusCode } ;
1414use hyper_util:: rt:: TokioIo ;
1515use hyper_util:: service:: TowerToHyperService ;
16- use payjoin:: directory:: { ShortId , ShortIdError , ENCAPSULATED_MESSAGE_BYTES } ;
16+ use payjoin:: directory:: { ShortId , ShortIdError } ;
1717use tokio:: net:: TcpListener ;
1818#[ cfg( feature = "acme" ) ]
1919use tokio_rustls_acme:: AcmeConfig ;
2020use tokio_stream:: wrappers:: TcpListenerStream ;
2121use tokio_stream:: Stream ;
22- use tracing:: { debug, error, trace , warn} ;
22+ use tracing:: { debug, error, warn} ;
2323
2424pub use crate :: db:: files:: Db as FilesDb ;
2525use crate :: db:: Db ;
@@ -28,14 +28,8 @@ use ohttp_relay::SentinelTag;
2828
2929pub use crate :: key_config:: * ;
3030
31- const CHACHA20_POLY1305_NONCE_LEN : usize = 32 ; // chacha20poly1305 n_k
32- const POLY1305_TAG_SIZE : usize = 16 ;
33- pub const BHTTP_REQ_BYTES : usize =
34- ENCAPSULATED_MESSAGE_BYTES - ( CHACHA20_POLY1305_NONCE_LEN + POLY1305_TAG_SIZE ) ;
3531const V1_MAX_BUFFER_SIZE : usize = 65536 ;
3632
37- const V1_REJECT_RES_JSON : & str =
38- r#"{{"errorCode": "original-psbt-rejected ", "message": "Body is not a string"}}"# ;
3933const V1_UNAVAILABLE_RES_JSON : & str = r#"{{"errorCode": "unavailable", "message": "V2 receiver offline. V1 sends require synchronous communications."}}"# ;
4034
4135pub ( crate ) mod db;
@@ -208,15 +202,14 @@ impl<D: Db> Service<D> {
208202 }
209203
210204 let mut response = match ( parts. method , path_segments. as_slice ( ) ) {
211- ( Method :: POST , [ "" , ".well-known" , "ohttp-gateway" ] ) =>
212- self . handle_ohttp_gateway ( body) . await ,
213205 ( Method :: GET , [ "" , ".well-known" , "ohttp-gateway" ] ) =>
214206 self . handle_ohttp_gateway_get ( & query) . await ,
215- ( Method :: POST , [ "" , "" ] ) => self . handle_ohttp_gateway ( body) . await ,
216207 ( Method :: GET , [ "" , "ohttp-keys" ] ) => self . get_ohttp_keys ( ) . await ,
217- ( Method :: POST , [ "" , id] ) => self . post_fallback_v1 ( id, query, body) . await ,
218208 ( Method :: GET , [ "" , "health" ] ) => health_check ( ) . await ,
219209 ( Method :: GET , [ "" , "" ] ) => handle_directory_home_path ( ) . await ,
210+ ( Method :: POST , [ "" , id] ) => self . post_mailbox_or_v1 ( id, query, body) . await ,
211+ ( Method :: GET , [ "" , id] ) => self . get_mailbox ( id) . await ,
212+ ( Method :: PUT , [ "" , id] ) => self . put_payjoin_v1 ( id, body) . await ,
220213 _ => Ok ( not_found ( ) ) ,
221214 }
222215 . unwrap_or_else ( |e| e. to_response ( ) ) ;
@@ -227,132 +220,76 @@ impl<D: Db> Service<D> {
227220 Ok ( response)
228221 }
229222
230- async fn handle_ohttp_gateway < B > (
223+ async fn post_mailbox_or_v1 < B > (
231224 & self ,
225+ id : & str ,
226+ query : String ,
232227 body : B ,
233228 ) -> Result < Response < BoxBody < Bytes , hyper:: Error > > , HandlerError >
234229 where
235230 B : Body < Data = Bytes > + Send + ' static ,
236231 B :: Error : Into < BoxError > ,
237232 {
238- let ohttp_body = body
233+ let body_bytes = body
239234 . collect ( )
240235 . await
241236 . map_err ( |e| HandlerError :: BadRequest ( anyhow:: anyhow!( e. into( ) ) ) ) ?
242237 . to_bytes ( ) ;
243238
244- let ( bhttp_req, res_ctx) = self
245- . ohttp
246- . decapsulate ( & ohttp_body)
247- . map_err ( |e| HandlerError :: OhttpKeyRejection ( e. into ( ) ) ) ?;
248- let mut cursor = std:: io:: Cursor :: new ( bhttp_req) ;
249- let req = bhttp:: Message :: read_bhttp ( & mut cursor)
250- . map_err ( |e| HandlerError :: BadRequest ( e. into ( ) ) ) ?;
251- let uri = Uri :: builder ( )
252- . scheme ( req. control ( ) . scheme ( ) . unwrap_or_default ( ) )
253- . authority ( req. control ( ) . authority ( ) . unwrap_or_default ( ) )
254- . path_and_query ( req. control ( ) . path ( ) . unwrap_or_default ( ) )
255- . build ( ) ?;
256- let body = req. content ( ) . to_vec ( ) ;
257- let mut http_req =
258- Request :: builder ( ) . uri ( uri) . method ( req. control ( ) . method ( ) . unwrap_or_default ( ) ) ;
259- for header in req. header ( ) . fields ( ) {
260- http_req = http_req. header ( header. name ( ) , header. value ( ) )
261- }
262- let request = http_req. body ( full ( body) ) ?;
263-
264- let response = self . handle_v2 ( request) . await ?;
265-
266- let ( parts, body) = response. into_parts ( ) ;
267- let mut bhttp_res = bhttp:: Message :: response (
268- bhttp:: StatusCode :: try_from ( parts. status . as_u16 ( ) )
269- . map_err ( |e| HandlerError :: InternalServerError ( e. into ( ) ) ) ?,
270- ) ;
271- for ( name, value) in parts. headers . iter ( ) {
272- bhttp_res. put_header ( name. as_str ( ) , value. to_str ( ) . unwrap_or_default ( ) ) ;
273- }
274- let full_body = body
275- . collect ( )
276- . await
277- . map_err ( |e| HandlerError :: InternalServerError ( e. into ( ) ) ) ?
278- . to_bytes ( ) ;
279- bhttp_res. write_content ( & full_body) ;
280- let mut bhttp_bytes = Vec :: new ( ) ;
281- bhttp_res
282- . write_bhttp ( bhttp:: Mode :: KnownLength , & mut bhttp_bytes)
283- . map_err ( |e| HandlerError :: InternalServerError ( e. into ( ) ) ) ?;
284- bhttp_bytes. resize ( BHTTP_REQ_BYTES , 0 ) ;
285- let ohttp_res = res_ctx
286- . encapsulate ( & bhttp_bytes)
287- . map_err ( |e| HandlerError :: InternalServerError ( e. into ( ) ) ) ?;
288- assert ! ( ohttp_res. len( ) == ENCAPSULATED_MESSAGE_BYTES , "Unexpected OHTTP response size" ) ;
289- Ok ( Response :: new ( full ( ohttp_res) ) )
290- }
291-
292- async fn handle_v2 (
293- & self ,
294- req : Request < BoxBody < Bytes , hyper:: Error > > ,
295- ) -> Result < Response < BoxBody < Bytes , hyper:: Error > > , HandlerError > {
296- let path = req. uri ( ) . path ( ) . to_string ( ) ;
297- let ( parts, body) = req. into_parts ( ) ;
298-
299- let path_segments: Vec < & str > = path. split ( '/' ) . collect ( ) ;
300- debug ! ( "handle_v2: {:?}" , & path_segments) ;
301- match ( parts. method , path_segments. as_slice ( ) ) {
302- ( Method :: POST , & [ "" , id] ) => self . post_mailbox ( id, body) . await ,
303- ( Method :: GET , & [ "" , id] ) => self . get_mailbox ( id) . await ,
304- ( Method :: PUT , & [ "" , id] ) => self . put_payjoin_v1 ( id, body) . await ,
305- _ => Ok ( not_found ( ) ) ,
239+ if body_bytes. len ( ) > V1_MAX_BUFFER_SIZE {
240+ return Err ( HandlerError :: PayloadTooLarge ) ;
306241 }
307- }
308-
309- async fn post_mailbox (
310- & self ,
311- id : & str ,
312- body : BoxBody < Bytes , hyper:: Error > ,
313- ) -> Result < Response < BoxBody < Bytes , hyper:: Error > > , HandlerError > {
314- let none_response = Response :: builder ( ) . status ( StatusCode :: OK ) . body ( empty ( ) ) ?;
315- trace ! ( "post_mailbox" ) ;
316242
317243 let id = ShortId :: from_str ( id) ?;
318244
319- let req = body
320- . collect ( )
321- . await
322- . map_err ( |e| HandlerError :: InternalServerError ( e. into ( ) ) ) ?
323- . to_bytes ( ) ;
324- if req. len ( ) > V1_MAX_BUFFER_SIZE {
325- return Err ( HandlerError :: PayloadTooLarge ) ;
326- }
327-
328- match self . db . post_v2_payload ( & id, req. into ( ) ) . await {
329- Ok ( _) => Ok ( none_response) ,
330- Err ( e) => Err ( HandlerError :: InternalServerError ( e. into ( ) ) ) ,
245+ if let Ok ( body_str) = String :: from_utf8 ( body_bytes. to_vec ( ) ) {
246+ let v2_compat_body = format ! ( "{body_str}\n {query}" ) ;
247+ let none_response = Response :: builder ( )
248+ . status ( StatusCode :: SERVICE_UNAVAILABLE )
249+ . body ( full ( V1_UNAVAILABLE_RES_JSON ) ) ?;
250+ handle_peek (
251+ self . db . post_v1_request_and_wait_for_response ( & id, v2_compat_body. into ( ) ) . await ,
252+ none_response,
253+ )
254+ } else {
255+ let none_response = Response :: builder ( ) . status ( StatusCode :: OK ) . body ( empty ( ) ) ?;
256+ match self . db . post_v2_payload ( & id, body_bytes. into ( ) ) . await {
257+ Ok ( _) => Ok ( none_response) ,
258+ Err ( e) => Err ( HandlerError :: InternalServerError ( e. into ( ) ) ) ,
259+ }
331260 }
332261 }
333262
334263 async fn get_mailbox (
335264 & self ,
336265 id : & str ,
337266 ) -> Result < Response < BoxBody < Bytes , hyper:: Error > > , HandlerError > {
338- trace ! ( "get_mailbox" ) ;
339267 let id = ShortId :: from_str ( id) ?;
340268 let timeout_response = Response :: builder ( ) . status ( StatusCode :: ACCEPTED ) . body ( empty ( ) ) ?;
341269 handle_peek ( self . db . wait_for_v2_payload ( & id) . await , timeout_response)
342270 }
343- async fn put_payjoin_v1 (
271+
272+ async fn put_payjoin_v1 < B > (
344273 & self ,
345274 id : & str ,
346- body : BoxBody < Bytes , hyper:: Error > ,
347- ) -> Result < Response < BoxBody < Bytes , hyper:: Error > > , HandlerError > {
348- trace ! ( "Put_payjoin_v1" ) ;
275+ body : B ,
276+ ) -> Result < Response < BoxBody < Bytes , hyper:: Error > > , HandlerError >
277+ where
278+ B : Body < Data = Bytes > + Send + ' static ,
279+ B :: Error : Into < BoxError > ,
280+ {
349281 let ok_response = Response :: builder ( ) . status ( StatusCode :: OK ) . body ( empty ( ) ) ?;
350282
351283 let id = ShortId :: from_str ( id) ?;
352284 let req = body
353285 . collect ( )
354286 . await
355- . map_err ( |e| HandlerError :: InternalServerError ( e. into ( ) ) ) ?
287+ . map_err ( |e| {
288+ HandlerError :: InternalServerError ( anyhow:: anyhow!(
289+ "Failed to read body: {}" ,
290+ e. into( )
291+ ) )
292+ } ) ?
356293 . to_bytes ( ) ;
357294 if req. len ( ) > V1_MAX_BUFFER_SIZE {
358295 return Err ( HandlerError :: PayloadTooLarge ) ;
@@ -364,41 +301,6 @@ impl<D: Db> Service<D> {
364301 }
365302 }
366303
367- async fn post_fallback_v1 < B > (
368- & self ,
369- id : & str ,
370- query : String ,
371- body : B ,
372- ) -> Result < Response < BoxBody < Bytes , hyper:: Error > > , HandlerError >
373- where
374- B : Body < Data = Bytes > + Send + ' static ,
375- B :: Error : Into < BoxError > ,
376- {
377- trace ! ( "Post fallback v1" ) ;
378- let none_response = Response :: builder ( )
379- . status ( StatusCode :: SERVICE_UNAVAILABLE )
380- . body ( full ( V1_UNAVAILABLE_RES_JSON ) ) ?;
381- let bad_request_body_res =
382- Response :: builder ( ) . status ( StatusCode :: BAD_REQUEST ) . body ( full ( V1_REJECT_RES_JSON ) ) ?;
383-
384- let body_bytes = match body. collect ( ) . await {
385- Ok ( bytes) => bytes. to_bytes ( ) ,
386- Err ( _) => return Ok ( bad_request_body_res) ,
387- } ;
388-
389- let body_str = match String :: from_utf8 ( body_bytes. to_vec ( ) ) {
390- Ok ( body_str) => body_str,
391- Err ( _) => return Ok ( bad_request_body_res) ,
392- } ;
393-
394- let v2_compat_body = format ! ( "{body_str}\n {query}" ) ;
395- let id = ShortId :: from_str ( id) ?;
396- handle_peek (
397- self . db . post_v1_request_and_wait_for_response ( & id, v2_compat_body. into ( ) ) . await ,
398- none_response,
399- )
400- }
401-
402304 async fn handle_ohttp_gateway_get (
403305 & self ,
404306 query : & str ,
@@ -466,10 +368,6 @@ async fn health_check() -> Result<Response<BoxBody<Bytes, hyper::Error>>, Handle
466368
467369async fn handle_directory_home_path ( ) -> Result < Response < BoxBody < Bytes , hyper:: Error > > , HandlerError >
468370{
469- let mut res = Response :: new ( empty ( ) ) ;
470- * res. status_mut ( ) = StatusCode :: OK ;
471- res. headers_mut ( ) . insert ( CONTENT_TYPE , HeaderValue :: from_static ( "text/html" ) ) ;
472-
473371 let html = r#"
474372<!DOCTYPE html>
475373<html lang="en">
@@ -521,7 +419,9 @@ async fn handle_directory_home_path() -> Result<Response<BoxBody<Bytes, hyper::E
521419</html>
522420"# ;
523421
524- * res. body_mut ( ) = full ( html) ;
422+ let mut res = Response :: new ( full ( html) ) ;
423+ * res. status_mut ( ) = StatusCode :: OK ;
424+ res. headers_mut ( ) . insert ( CONTENT_TYPE , HeaderValue :: from_static ( "text/html" ) ) ;
525425 Ok ( res)
526426}
527427
@@ -531,7 +431,6 @@ enum HandlerError {
531431 InternalServerError ( anyhow:: Error ) ,
532432 ServiceUnavailable ( anyhow:: Error ) ,
533433 SenderGone ( anyhow:: Error ) ,
534- OhttpKeyRejection ( anyhow:: Error ) ,
535434 BadRequest ( anyhow:: Error ) ,
536435 Forbidden ( anyhow:: Error ) ,
537436}
@@ -553,15 +452,6 @@ impl HandlerError {
553452 error ! ( "Sender gone: {}" , e) ;
554453 * res. status_mut ( ) = StatusCode :: GONE
555454 }
556- HandlerError :: OhttpKeyRejection ( e) => {
557- const OHTTP_KEY_REJECTION_RES_JSON : & str = r#"{"type":"https://iana.org/assignments/http-problem-types#ohttp-key", "title": "key identifier unknown"}"# ;
558-
559- warn ! ( "Bad request: Key configuration rejected: {}" , e) ;
560- * res. status_mut ( ) = StatusCode :: BAD_REQUEST ;
561- res. headers_mut ( )
562- . insert ( CONTENT_TYPE , HeaderValue :: from_static ( "application/problem+json" ) ) ;
563- * res. body_mut ( ) = full ( OHTTP_KEY_REJECTION_RES_JSON ) ;
564- }
565455 HandlerError :: BadRequest ( e) => {
566456 warn ! ( "Bad request: {}" , e) ;
567457 * res. status_mut ( ) = StatusCode :: BAD_REQUEST
0 commit comments