proxy_wasm/
hostcalls.rs

1// Copyright 2020 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::dispatcher;
16use crate::types::*;
17use std::ptr::{null, null_mut};
18use std::time::{Duration, SystemTime, UNIX_EPOCH};
19
20extern "C" {
21    fn proxy_log(level: LogLevel, message_data: *const u8, message_size: usize) -> Status;
22}
23
24pub fn log(level: LogLevel, message: &str) -> Result<(), Status> {
25    unsafe {
26        match proxy_log(level, message.as_ptr(), message.len()) {
27            Status::Ok => Ok(()),
28            status => panic!("unexpected status: {}", status as u32),
29        }
30    }
31}
32
33extern "C" {
34    fn proxy_get_log_level(return_level: *mut LogLevel) -> Status;
35}
36
37pub fn get_log_level() -> Result<LogLevel, Status> {
38    let mut return_level: LogLevel = LogLevel::Trace;
39    unsafe {
40        match proxy_get_log_level(&mut return_level) {
41            Status::Ok => Ok(return_level),
42            status => panic!("unexpected status: {}", status as u32),
43        }
44    }
45}
46
47extern "C" {
48    fn proxy_get_current_time_nanoseconds(return_time: *mut u64) -> Status;
49}
50
51pub fn get_current_time() -> Result<SystemTime, Status> {
52    let mut return_time: u64 = 0;
53    unsafe {
54        match proxy_get_current_time_nanoseconds(&mut return_time) {
55            Status::Ok => Ok(UNIX_EPOCH + Duration::from_nanos(return_time)),
56            status => panic!("unexpected status: {}", status as u32),
57        }
58    }
59}
60
61extern "C" {
62    fn proxy_set_tick_period_milliseconds(period: u32) -> Status;
63}
64
65pub fn set_tick_period(period: Duration) -> Result<(), Status> {
66    unsafe {
67        match proxy_set_tick_period_milliseconds(period.as_millis() as u32) {
68            Status::Ok => Ok(()),
69            status => panic!("unexpected status: {}", status as u32),
70        }
71    }
72}
73
74extern "C" {
75    fn proxy_get_buffer_bytes(
76        buffer_type: BufferType,
77        start: usize,
78        max_size: usize,
79        return_buffer_data: *mut *mut u8,
80        return_buffer_size: *mut usize,
81    ) -> Status;
82}
83
84pub fn get_buffer(
85    buffer_type: BufferType,
86    start: usize,
87    max_size: usize,
88) -> Result<Option<Bytes>, Status> {
89    let mut return_data: *mut u8 = null_mut();
90    let mut return_size: usize = 0;
91    unsafe {
92        match proxy_get_buffer_bytes(
93            buffer_type,
94            start,
95            max_size,
96            &mut return_data,
97            &mut return_size,
98        ) {
99            Status::Ok => {
100                if !return_data.is_null() {
101                    Ok(Some(Vec::from_raw_parts(
102                        return_data,
103                        return_size,
104                        return_size,
105                    )))
106                } else {
107                    Ok(None)
108                }
109            }
110            Status::NotFound => Ok(None),
111            status => panic!("unexpected status: {}", status as u32),
112        }
113    }
114}
115
116extern "C" {
117    fn proxy_set_buffer_bytes(
118        buffer_type: BufferType,
119        start: usize,
120        size: usize,
121        buffer_data: *const u8,
122        buffer_size: usize,
123    ) -> Status;
124}
125
126pub fn set_buffer(
127    buffer_type: BufferType,
128    start: usize,
129    size: usize,
130    value: &[u8],
131) -> Result<(), Status> {
132    unsafe {
133        match proxy_set_buffer_bytes(buffer_type, start, size, value.as_ptr(), value.len()) {
134            Status::Ok => Ok(()),
135            status => panic!("unexpected status: {}", status as u32),
136        }
137    }
138}
139
140extern "C" {
141    fn proxy_get_header_map_pairs(
142        map_type: MapType,
143        return_map_data: *mut *mut u8,
144        return_map_size: *mut usize,
145    ) -> Status;
146}
147
148pub fn get_map(map_type: MapType) -> Result<Vec<(String, String)>, Status> {
149    unsafe {
150        let mut return_data: *mut u8 = null_mut();
151        let mut return_size: usize = 0;
152        match proxy_get_header_map_pairs(map_type, &mut return_data, &mut return_size) {
153            Status::Ok => {
154                if !return_data.is_null() {
155                    let serialized_map = std::slice::from_raw_parts(return_data, return_size);
156                    Ok(utils::deserialize_map(serialized_map))
157                } else {
158                    Ok(Vec::new())
159                }
160            }
161            status => panic!("unexpected status: {}", status as u32),
162        }
163    }
164}
165
166pub fn get_map_bytes(map_type: MapType) -> Result<Vec<(String, Bytes)>, Status> {
167    unsafe {
168        let mut return_data: *mut u8 = null_mut();
169        let mut return_size: usize = 0;
170        match proxy_get_header_map_pairs(map_type, &mut return_data, &mut return_size) {
171            Status::Ok => {
172                if !return_data.is_null() {
173                    let serialized_map = std::slice::from_raw_parts(return_data, return_size);
174                    Ok(utils::deserialize_map_bytes(serialized_map))
175                } else {
176                    Ok(Vec::new())
177                }
178            }
179            status => panic!("unexpected status: {}", status as u32),
180        }
181    }
182}
183
184extern "C" {
185    fn proxy_set_header_map_pairs(
186        map_type: MapType,
187        map_data: *const u8,
188        map_size: usize,
189    ) -> Status;
190}
191
192pub fn set_map(map_type: MapType, map: Vec<(&str, &str)>) -> Result<(), Status> {
193    let serialized_map = utils::serialize_map(&map);
194    unsafe {
195        match proxy_set_header_map_pairs(map_type, serialized_map.as_ptr(), serialized_map.len()) {
196            Status::Ok => Ok(()),
197            status => panic!("unexpected status: {}", status as u32),
198        }
199    }
200}
201
202pub fn set_map_bytes(map_type: MapType, map: Vec<(&str, &[u8])>) -> Result<(), Status> {
203    let serialized_map = utils::serialize_map_bytes(&map);
204    unsafe {
205        match proxy_set_header_map_pairs(map_type, serialized_map.as_ptr(), serialized_map.len()) {
206            Status::Ok => Ok(()),
207            status => panic!("unexpected status: {}", status as u32),
208        }
209    }
210}
211
212extern "C" {
213    fn proxy_get_header_map_value(
214        map_type: MapType,
215        key_data: *const u8,
216        key_size: usize,
217        return_value_data: *mut *mut u8,
218        return_value_size: *mut usize,
219    ) -> Status;
220}
221
222pub fn get_map_value(map_type: MapType, key: &str) -> Result<Option<String>, Status> {
223    let mut return_data: *mut u8 = null_mut();
224    let mut return_size: usize = 0;
225    unsafe {
226        match proxy_get_header_map_value(
227            map_type,
228            key.as_ptr(),
229            key.len(),
230            &mut return_data,
231            &mut return_size,
232        ) {
233            Status::Ok => {
234                if !return_data.is_null() {
235                    Ok(Some(
236                        String::from_utf8(Vec::from_raw_parts(
237                            return_data,
238                            return_size,
239                            return_size,
240                        ))
241                        .unwrap(),
242                    ))
243                } else {
244                    Ok(Some(String::new()))
245                }
246            }
247            Status::NotFound => Ok(None),
248            status => panic!("unexpected status: {}", status as u32),
249        }
250    }
251}
252
253pub fn get_map_value_bytes(map_type: MapType, key: &str) -> Result<Option<Bytes>, Status> {
254    let mut return_data: *mut u8 = null_mut();
255    let mut return_size: usize = 0;
256    unsafe {
257        match proxy_get_header_map_value(
258            map_type,
259            key.as_ptr(),
260            key.len(),
261            &mut return_data,
262            &mut return_size,
263        ) {
264            Status::Ok => {
265                if !return_data.is_null() {
266                    Ok(Some(Vec::from_raw_parts(
267                        return_data,
268                        return_size,
269                        return_size,
270                    )))
271                } else {
272                    Ok(Some(Vec::new()))
273                }
274            }
275            Status::NotFound => Ok(None),
276            status => panic!("unexpected status: {}", status as u32),
277        }
278    }
279}
280
281extern "C" {
282    fn proxy_remove_header_map_value(
283        map_type: MapType,
284        key_data: *const u8,
285        key_size: usize,
286    ) -> Status;
287}
288
289pub fn remove_map_value(map_type: MapType, key: &str) -> Result<(), Status> {
290    unsafe {
291        match proxy_remove_header_map_value(map_type, key.as_ptr(), key.len()) {
292            Status::Ok => Ok(()),
293            status => panic!("unexpected status: {}", status as u32),
294        }
295    }
296}
297
298extern "C" {
299    fn proxy_replace_header_map_value(
300        map_type: MapType,
301        key_data: *const u8,
302        key_size: usize,
303        value_data: *const u8,
304        value_size: usize,
305    ) -> Status;
306}
307
308pub fn set_map_value(map_type: MapType, key: &str, value: Option<&str>) -> Result<(), Status> {
309    unsafe {
310        if let Some(value) = value {
311            match proxy_replace_header_map_value(
312                map_type,
313                key.as_ptr(),
314                key.len(),
315                value.as_ptr(),
316                value.len(),
317            ) {
318                Status::Ok => Ok(()),
319                status => panic!("unexpected status: {}", status as u32),
320            }
321        } else {
322            match proxy_remove_header_map_value(map_type, key.as_ptr(), key.len()) {
323                Status::Ok => Ok(()),
324                status => panic!("unexpected status: {}", status as u32),
325            }
326        }
327    }
328}
329
330pub fn set_map_value_bytes(
331    map_type: MapType,
332    key: &str,
333    value: Option<&[u8]>,
334) -> Result<(), Status> {
335    unsafe {
336        if let Some(value) = value {
337            match proxy_replace_header_map_value(
338                map_type,
339                key.as_ptr(),
340                key.len(),
341                value.as_ptr(),
342                value.len(),
343            ) {
344                Status::Ok => Ok(()),
345                status => panic!("unexpected status: {}", status as u32),
346            }
347        } else {
348            match proxy_remove_header_map_value(map_type, key.as_ptr(), key.len()) {
349                Status::Ok => Ok(()),
350                status => panic!("unexpected status: {}", status as u32),
351            }
352        }
353    }
354}
355
356extern "C" {
357    fn proxy_add_header_map_value(
358        map_type: MapType,
359        key_data: *const u8,
360        key_size: usize,
361        value_data: *const u8,
362        value_size: usize,
363    ) -> Status;
364}
365
366pub fn add_map_value(map_type: MapType, key: &str, value: &str) -> Result<(), Status> {
367    unsafe {
368        match proxy_add_header_map_value(
369            map_type,
370            key.as_ptr(),
371            key.len(),
372            value.as_ptr(),
373            value.len(),
374        ) {
375            Status::Ok => Ok(()),
376            status => panic!("unexpected status: {}", status as u32),
377        }
378    }
379}
380
381pub fn add_map_value_bytes(map_type: MapType, key: &str, value: &[u8]) -> Result<(), Status> {
382    unsafe {
383        match proxy_add_header_map_value(
384            map_type,
385            key.as_ptr(),
386            key.len(),
387            value.as_ptr(),
388            value.len(),
389        ) {
390            Status::Ok => Ok(()),
391            status => panic!("unexpected status: {}", status as u32),
392        }
393    }
394}
395
396extern "C" {
397    fn proxy_get_property(
398        path_data: *const u8,
399        path_size: usize,
400        return_value_data: *mut *mut u8,
401        return_value_size: *mut usize,
402    ) -> Status;
403}
404
405pub fn get_property(path: Vec<&str>) -> Result<Option<Bytes>, Status> {
406    let serialized_path = utils::serialize_property_path(path);
407    let mut return_data: *mut u8 = null_mut();
408    let mut return_size: usize = 0;
409    unsafe {
410        match proxy_get_property(
411            serialized_path.as_ptr(),
412            serialized_path.len(),
413            &mut return_data,
414            &mut return_size,
415        ) {
416            Status::Ok => {
417                if !return_data.is_null() {
418                    Ok(Some(Vec::from_raw_parts(
419                        return_data,
420                        return_size,
421                        return_size,
422                    )))
423                } else {
424                    Ok(None)
425                }
426            }
427            Status::NotFound => Ok(None),
428            Status::SerializationFailure => Err(Status::SerializationFailure),
429            Status::InternalFailure => Err(Status::InternalFailure),
430            status => panic!("unexpected status: {}", status as u32),
431        }
432    }
433}
434
435extern "C" {
436    fn proxy_set_property(
437        path_data: *const u8,
438        path_size: usize,
439        value_data: *const u8,
440        value_size: usize,
441    ) -> Status;
442}
443
444pub fn set_property(path: Vec<&str>, value: Option<&[u8]>) -> Result<(), Status> {
445    let serialized_path = utils::serialize_property_path(path);
446    unsafe {
447        match proxy_set_property(
448            serialized_path.as_ptr(),
449            serialized_path.len(),
450            value.map_or(null(), |value| value.as_ptr()),
451            value.map_or(0, |value| value.len()),
452        ) {
453            Status::Ok => Ok(()),
454            status => panic!("unexpected status: {}", status as u32),
455        }
456    }
457}
458
459extern "C" {
460    fn proxy_get_shared_data(
461        key_data: *const u8,
462        key_size: usize,
463        return_value_data: *mut *mut u8,
464        return_value_size: *mut usize,
465        return_cas: *mut u32,
466    ) -> Status;
467}
468
469pub fn get_shared_data(key: &str) -> Result<(Option<Bytes>, Option<u32>), Status> {
470    let mut return_data: *mut u8 = null_mut();
471    let mut return_size: usize = 0;
472    let mut return_cas: u32 = 0;
473    unsafe {
474        match proxy_get_shared_data(
475            key.as_ptr(),
476            key.len(),
477            &mut return_data,
478            &mut return_size,
479            &mut return_cas,
480        ) {
481            Status::Ok => {
482                let cas = match return_cas {
483                    0 => None,
484                    cas => Some(cas),
485                };
486                if !return_data.is_null() {
487                    Ok((
488                        Some(Vec::from_raw_parts(return_data, return_size, return_size)),
489                        cas,
490                    ))
491                } else {
492                    Ok((None, cas))
493                }
494            }
495            Status::NotFound => Ok((None, None)),
496            status => panic!("unexpected status: {}", status as u32),
497        }
498    }
499}
500
501extern "C" {
502    fn proxy_set_shared_data(
503        key_data: *const u8,
504        key_size: usize,
505        value_data: *const u8,
506        value_size: usize,
507        cas: u32,
508    ) -> Status;
509}
510
511pub fn set_shared_data(key: &str, value: Option<&[u8]>, cas: Option<u32>) -> Result<(), Status> {
512    unsafe {
513        match proxy_set_shared_data(
514            key.as_ptr(),
515            key.len(),
516            value.map_or(null(), |value| value.as_ptr()),
517            value.map_or(0, |value| value.len()),
518            cas.unwrap_or(0),
519        ) {
520            Status::Ok => Ok(()),
521            Status::CasMismatch => Err(Status::CasMismatch),
522            status => panic!("unexpected status: {}", status as u32),
523        }
524    }
525}
526
527extern "C" {
528    fn proxy_register_shared_queue(
529        name_data: *const u8,
530        name_size: usize,
531        return_id: *mut u32,
532    ) -> Status;
533}
534
535pub fn register_shared_queue(name: &str) -> Result<u32, Status> {
536    unsafe {
537        let mut return_id: u32 = 0;
538        match proxy_register_shared_queue(name.as_ptr(), name.len(), &mut return_id) {
539            Status::Ok => Ok(return_id),
540            status => panic!("unexpected status: {}", status as u32),
541        }
542    }
543}
544
545extern "C" {
546    fn proxy_resolve_shared_queue(
547        vm_id_data: *const u8,
548        vm_id_size: usize,
549        name_data: *const u8,
550        name_size: usize,
551        return_id: *mut u32,
552    ) -> Status;
553}
554
555pub fn resolve_shared_queue(vm_id: &str, name: &str) -> Result<Option<u32>, Status> {
556    let mut return_id: u32 = 0;
557    unsafe {
558        match proxy_resolve_shared_queue(
559            vm_id.as_ptr(),
560            vm_id.len(),
561            name.as_ptr(),
562            name.len(),
563            &mut return_id,
564        ) {
565            Status::Ok => Ok(Some(return_id)),
566            Status::NotFound => Ok(None),
567            status => panic!("unexpected status: {}", status as u32),
568        }
569    }
570}
571
572extern "C" {
573    fn proxy_dequeue_shared_queue(
574        queue_id: u32,
575        return_value_data: *mut *mut u8,
576        return_value_size: *mut usize,
577    ) -> Status;
578}
579
580pub fn dequeue_shared_queue(queue_id: u32) -> Result<Option<Bytes>, Status> {
581    let mut return_data: *mut u8 = null_mut();
582    let mut return_size: usize = 0;
583    unsafe {
584        match proxy_dequeue_shared_queue(queue_id, &mut return_data, &mut return_size) {
585            Status::Ok => {
586                if !return_data.is_null() {
587                    Ok(Some(Vec::from_raw_parts(
588                        return_data,
589                        return_size,
590                        return_size,
591                    )))
592                } else {
593                    Ok(None)
594                }
595            }
596            Status::Empty => Ok(None),
597            Status::NotFound => Err(Status::NotFound),
598            status => panic!("unexpected status: {}", status as u32),
599        }
600    }
601}
602
603extern "C" {
604    fn proxy_enqueue_shared_queue(
605        queue_id: u32,
606        value_data: *const u8,
607        value_size: usize,
608    ) -> Status;
609}
610
611pub fn enqueue_shared_queue(queue_id: u32, value: Option<&[u8]>) -> Result<(), Status> {
612    unsafe {
613        match proxy_enqueue_shared_queue(
614            queue_id,
615            value.map_or(null(), |value| value.as_ptr()),
616            value.map_or(0, |value| value.len()),
617        ) {
618            Status::Ok => Ok(()),
619            Status::NotFound => Err(Status::NotFound),
620            status => panic!("unexpected status: {}", status as u32),
621        }
622    }
623}
624
625extern "C" {
626    fn proxy_continue_stream(stream_type: StreamType) -> Status;
627}
628
629pub fn resume_downstream() -> Result<(), Status> {
630    unsafe {
631        match proxy_continue_stream(StreamType::Downstream) {
632            Status::Ok => Ok(()),
633            status => panic!("unexpected status: {}", status as u32),
634        }
635    }
636}
637
638pub fn resume_upstream() -> Result<(), Status> {
639    unsafe {
640        match proxy_continue_stream(StreamType::Upstream) {
641            Status::Ok => Ok(()),
642            status => panic!("unexpected status: {}", status as u32),
643        }
644    }
645}
646
647pub fn resume_http_request() -> Result<(), Status> {
648    unsafe {
649        match proxy_continue_stream(StreamType::HttpRequest) {
650            Status::Ok => Ok(()),
651            status => panic!("unexpected status: {}", status as u32),
652        }
653    }
654}
655
656pub fn resume_http_response() -> Result<(), Status> {
657    unsafe {
658        match proxy_continue_stream(StreamType::HttpResponse) {
659            Status::Ok => Ok(()),
660            status => panic!("unexpected status: {}", status as u32),
661        }
662    }
663}
664
665extern "C" {
666    fn proxy_close_stream(stream_type: StreamType) -> Status;
667}
668
669pub fn close_downstream() -> Result<(), Status> {
670    unsafe {
671        match proxy_close_stream(StreamType::Downstream) {
672            Status::Ok => Ok(()),
673            status => panic!("unexpected status: {}", status as u32),
674        }
675    }
676}
677pub fn close_upstream() -> Result<(), Status> {
678    unsafe {
679        match proxy_close_stream(StreamType::Upstream) {
680            Status::Ok => Ok(()),
681            status => panic!("unexpected status: {}", status as u32),
682        }
683    }
684}
685
686pub fn reset_http_request() -> Result<(), Status> {
687    unsafe {
688        match proxy_close_stream(StreamType::HttpRequest) {
689            Status::Ok => Ok(()),
690            status => panic!("unexpected status: {}", status as u32),
691        }
692    }
693}
694
695pub fn reset_http_response() -> Result<(), Status> {
696    unsafe {
697        match proxy_close_stream(StreamType::HttpResponse) {
698            Status::Ok => Ok(()),
699            status => panic!("unexpected status: {}", status as u32),
700        }
701    }
702}
703
704extern "C" {
705    fn proxy_send_local_response(
706        status_code: u32,
707        status_code_details_data: *const u8,
708        status_code_details_size: usize,
709        body_data: *const u8,
710        body_size: usize,
711        headers_data: *const u8,
712        headers_size: usize,
713        grpc_status: i32,
714    ) -> Status;
715}
716
717pub fn send_http_response(
718    status_code: u32,
719    headers: Vec<(&str, &str)>,
720    body: Option<&[u8]>,
721) -> Result<(), Status> {
722    let serialized_headers = utils::serialize_map(&headers);
723    unsafe {
724        match proxy_send_local_response(
725            status_code,
726            null(),
727            0,
728            body.map_or(null(), |body| body.as_ptr()),
729            body.map_or(0, |body| body.len()),
730            serialized_headers.as_ptr(),
731            serialized_headers.len(),
732            -1,
733        ) {
734            Status::Ok => Ok(()),
735            status => panic!("unexpected status: {}", status as u32),
736        }
737    }
738}
739
740pub fn send_grpc_response(
741    grpc_status: GrpcStatusCode,
742    grpc_status_message: Option<&str>,
743    custom_metadata: Vec<(&str, &[u8])>,
744) -> Result<(), Status> {
745    let serialized_custom_metadata = utils::serialize_map_bytes(&custom_metadata);
746    unsafe {
747        match proxy_send_local_response(
748            200,
749            null(),
750            0,
751            grpc_status_message.map_or(null(), |grpc_status_message| grpc_status_message.as_ptr()),
752            grpc_status_message.map_or(0, |grpc_status_message| grpc_status_message.len()),
753            serialized_custom_metadata.as_ptr(),
754            serialized_custom_metadata.len(),
755            grpc_status as i32,
756        ) {
757            Status::Ok => Ok(()),
758            status => panic!("unexpected status: {}", status as u32),
759        }
760    }
761}
762
763extern "C" {
764    fn proxy_http_call(
765        upstream_data: *const u8,
766        upstream_size: usize,
767        headers_data: *const u8,
768        headers_size: usize,
769        body_data: *const u8,
770        body_size: usize,
771        trailers_data: *const u8,
772        trailers_size: usize,
773        timeout: u32,
774        return_token: *mut u32,
775    ) -> Status;
776}
777
778pub fn dispatch_http_call(
779    upstream: &str,
780    headers: Vec<(&str, &str)>,
781    body: Option<&[u8]>,
782    trailers: Vec<(&str, &str)>,
783    timeout: Duration,
784) -> Result<u32, Status> {
785    let serialized_headers = utils::serialize_map(&headers);
786    let serialized_trailers = utils::serialize_map(&trailers);
787    let mut return_token: u32 = 0;
788    unsafe {
789        match proxy_http_call(
790            upstream.as_ptr(),
791            upstream.len(),
792            serialized_headers.as_ptr(),
793            serialized_headers.len(),
794            body.map_or(null(), |body| body.as_ptr()),
795            body.map_or(0, |body| body.len()),
796            serialized_trailers.as_ptr(),
797            serialized_trailers.len(),
798            timeout.as_millis() as u32,
799            &mut return_token,
800        ) {
801            Status::Ok => {
802                dispatcher::register_callout(return_token);
803                Ok(return_token)
804            }
805            Status::BadArgument => Err(Status::BadArgument),
806            Status::InternalFailure => Err(Status::InternalFailure),
807            status => panic!("unexpected status: {}", status as u32),
808        }
809    }
810}
811
812extern "C" {
813    fn proxy_grpc_call(
814        upstream_data: *const u8,
815        upstream_size: usize,
816        service_name_data: *const u8,
817        service_name_size: usize,
818        method_name_data: *const u8,
819        method_name_size: usize,
820        initial_metadata_data: *const u8,
821        initial_metadata_size: usize,
822        message_data_data: *const u8,
823        message_data_size: usize,
824        timeout: u32,
825        return_callout_id: *mut u32,
826    ) -> Status;
827}
828
829pub fn dispatch_grpc_call(
830    upstream_name: &str,
831    service_name: &str,
832    method_name: &str,
833    initial_metadata: Vec<(&str, &[u8])>,
834    message: Option<&[u8]>,
835    timeout: Duration,
836) -> Result<u32, Status> {
837    let mut return_callout_id = 0;
838    let serialized_initial_metadata = utils::serialize_map_bytes(&initial_metadata);
839    unsafe {
840        match proxy_grpc_call(
841            upstream_name.as_ptr(),
842            upstream_name.len(),
843            service_name.as_ptr(),
844            service_name.len(),
845            method_name.as_ptr(),
846            method_name.len(),
847            serialized_initial_metadata.as_ptr(),
848            serialized_initial_metadata.len(),
849            message.map_or(null(), |message| message.as_ptr()),
850            message.map_or(0, |message| message.len()),
851            timeout.as_millis() as u32,
852            &mut return_callout_id,
853        ) {
854            Status::Ok => {
855                dispatcher::register_grpc_callout(return_callout_id);
856                Ok(return_callout_id)
857            }
858            Status::ParseFailure => Err(Status::ParseFailure),
859            Status::InternalFailure => Err(Status::InternalFailure),
860            status => panic!("unexpected status: {}", status as u32),
861        }
862    }
863}
864
865extern "C" {
866    fn proxy_grpc_stream(
867        upstream_data: *const u8,
868        upstream_size: usize,
869        service_name_data: *const u8,
870        service_name_size: usize,
871        method_name_data: *const u8,
872        method_name_size: usize,
873        initial_metadata_data: *const u8,
874        initial_metadata_size: usize,
875        return_stream_id: *mut u32,
876    ) -> Status;
877}
878
879pub fn open_grpc_stream(
880    upstream_name: &str,
881    service_name: &str,
882    method_name: &str,
883    initial_metadata: Vec<(&str, &[u8])>,
884) -> Result<u32, Status> {
885    let mut return_stream_id = 0;
886    let serialized_initial_metadata = utils::serialize_map_bytes(&initial_metadata);
887    unsafe {
888        match proxy_grpc_stream(
889            upstream_name.as_ptr(),
890            upstream_name.len(),
891            service_name.as_ptr(),
892            service_name.len(),
893            method_name.as_ptr(),
894            method_name.len(),
895            serialized_initial_metadata.as_ptr(),
896            serialized_initial_metadata.len(),
897            &mut return_stream_id,
898        ) {
899            Status::Ok => {
900                dispatcher::register_grpc_stream(return_stream_id);
901                Ok(return_stream_id)
902            }
903            Status::ParseFailure => Err(Status::ParseFailure),
904            Status::InternalFailure => Err(Status::InternalFailure),
905            status => panic!("unexpected status: {}", status as u32),
906        }
907    }
908}
909
910extern "C" {
911    fn proxy_grpc_send(
912        token: u32,
913        message_ptr: *const u8,
914        message_len: usize,
915        end_stream: bool,
916    ) -> Status;
917}
918
919pub fn send_grpc_stream_message(
920    token: u32,
921    message: Option<&[u8]>,
922    end_stream: bool,
923) -> Result<(), Status> {
924    unsafe {
925        match proxy_grpc_send(
926            token,
927            message.map_or(null(), |message| message.as_ptr()),
928            message.map_or(0, |message| message.len()),
929            end_stream,
930        ) {
931            Status::Ok => Ok(()),
932            Status::BadArgument => Err(Status::BadArgument),
933            Status::NotFound => Err(Status::NotFound),
934            status => panic!("unexpected status: {}", status as u32),
935        }
936    }
937}
938
939extern "C" {
940    fn proxy_grpc_cancel(token_id: u32) -> Status;
941}
942
943pub fn cancel_grpc_call(token_id: u32) -> Result<(), Status> {
944    unsafe {
945        match proxy_grpc_cancel(token_id) {
946            Status::Ok => Ok(()),
947            Status::NotFound => Err(Status::NotFound),
948            status => panic!("unexpected status: {}", status as u32),
949        }
950    }
951}
952
953pub fn cancel_grpc_stream(token_id: u32) -> Result<(), Status> {
954    unsafe {
955        match proxy_grpc_cancel(token_id) {
956            Status::Ok => Ok(()),
957            Status::NotFound => Err(Status::NotFound),
958            status => panic!("unexpected status: {}", status as u32),
959        }
960    }
961}
962
963extern "C" {
964    fn proxy_grpc_close(token_id: u32) -> Status;
965}
966
967pub fn close_grpc_stream(token_id: u32) -> Result<(), Status> {
968    unsafe {
969        match proxy_grpc_close(token_id) {
970            Status::Ok => Ok(()),
971            Status::NotFound => Err(Status::NotFound),
972            status => panic!("unexpected status: {}", status as u32),
973        }
974    }
975}
976
977extern "C" {
978    fn proxy_get_status(
979        return_code: *mut u32,
980        return_message_data: *mut *mut u8,
981        return_message_size: *mut usize,
982    ) -> Status;
983}
984
985pub fn get_grpc_status() -> Result<(u32, Option<String>), Status> {
986    let mut return_code: u32 = 0;
987    let mut return_data: *mut u8 = null_mut();
988    let mut return_size: usize = 0;
989    unsafe {
990        match proxy_get_status(&mut return_code, &mut return_data, &mut return_size) {
991            Status::Ok => {
992                if !return_data.is_null() {
993                    Ok((
994                        return_code,
995                        Some(
996                            String::from_utf8(Vec::from_raw_parts(
997                                return_data,
998                                return_size,
999                                return_size,
1000                            ))
1001                            .unwrap(),
1002                        ),
1003                    ))
1004                } else {
1005                    Ok((return_code, None))
1006                }
1007            }
1008            status => panic!("unexpected status: {}", status as u32),
1009        }
1010    }
1011}
1012
1013extern "C" {
1014    fn proxy_set_effective_context(context_id: u32) -> Status;
1015}
1016
1017pub fn set_effective_context(context_id: u32) -> Result<(), Status> {
1018    unsafe {
1019        match proxy_set_effective_context(context_id) {
1020            Status::Ok => Ok(()),
1021            Status::BadArgument => Err(Status::BadArgument),
1022            status => panic!("unexpected status: {}", status as u32),
1023        }
1024    }
1025}
1026
1027extern "C" {
1028    fn proxy_call_foreign_function(
1029        function_name_data: *const u8,
1030        function_name_size: usize,
1031        arguments_data: *const u8,
1032        arguments_size: usize,
1033        results_data: *mut *mut u8,
1034        results_size: *mut usize,
1035    ) -> Status;
1036}
1037
1038pub fn call_foreign_function(
1039    function_name: &str,
1040    arguments: Option<&[u8]>,
1041) -> Result<Option<Bytes>, Status> {
1042    let mut return_data: *mut u8 = null_mut();
1043    let mut return_size: usize = 0;
1044    unsafe {
1045        match proxy_call_foreign_function(
1046            function_name.as_ptr(),
1047            function_name.len(),
1048            arguments.map_or(null(), |arguments| arguments.as_ptr()),
1049            arguments.map_or(0, |arguments| arguments.len()),
1050            &mut return_data,
1051            &mut return_size,
1052        ) {
1053            Status::Ok => {
1054                if !return_data.is_null() {
1055                    Ok(Some(Vec::from_raw_parts(
1056                        return_data,
1057                        return_size,
1058                        return_size,
1059                    )))
1060                } else {
1061                    Ok(None)
1062                }
1063            }
1064            Status::NotFound => Err(Status::NotFound),
1065            Status::BadArgument => Err(Status::BadArgument),
1066            Status::SerializationFailure => Err(Status::SerializationFailure),
1067            Status::InternalFailure => Err(Status::InternalFailure),
1068            status => panic!("unexpected status: {}", status as u32),
1069        }
1070    }
1071}
1072
1073extern "C" {
1074    fn proxy_done() -> Status;
1075}
1076
1077pub fn done() -> Result<(), Status> {
1078    unsafe {
1079        match proxy_done() {
1080            Status::Ok => Ok(()),
1081            status => panic!("unexpected status: {}", status as u32),
1082        }
1083    }
1084}
1085
1086extern "C" {
1087    fn proxy_define_metric(
1088        metric_type: MetricType,
1089        name_data: *const u8,
1090        name_size: usize,
1091        return_id: *mut u32,
1092    ) -> Status;
1093}
1094
1095pub fn define_metric(metric_type: MetricType, name: &str) -> Result<u32, Status> {
1096    let mut return_id: u32 = 0;
1097    unsafe {
1098        match proxy_define_metric(metric_type, name.as_ptr(), name.len(), &mut return_id) {
1099            Status::Ok => Ok(return_id),
1100            status => panic!("unexpected status: {}", status as u32),
1101        }
1102    }
1103}
1104
1105extern "C" {
1106    fn proxy_get_metric(metric_id: u32, return_value: *mut u64) -> Status;
1107}
1108
1109pub fn get_metric(metric_id: u32) -> Result<u64, Status> {
1110    let mut return_value: u64 = 0;
1111    unsafe {
1112        match proxy_get_metric(metric_id, &mut return_value) {
1113            Status::Ok => Ok(return_value),
1114            Status::NotFound => Err(Status::NotFound),
1115            Status::BadArgument => Err(Status::BadArgument),
1116            status => panic!("unexpected status: {}", status as u32),
1117        }
1118    }
1119}
1120
1121extern "C" {
1122    fn proxy_record_metric(metric_id: u32, value: u64) -> Status;
1123}
1124
1125pub fn record_metric(metric_id: u32, value: u64) -> Result<(), Status> {
1126    unsafe {
1127        match proxy_record_metric(metric_id, value) {
1128            Status::Ok => Ok(()),
1129            Status::NotFound => Err(Status::NotFound),
1130            status => panic!("unexpected status: {}", status as u32),
1131        }
1132    }
1133}
1134
1135extern "C" {
1136    fn proxy_increment_metric(metric_id: u32, offset: i64) -> Status;
1137}
1138
1139pub fn increment_metric(metric_id: u32, offset: i64) -> Result<(), Status> {
1140    unsafe {
1141        match proxy_increment_metric(metric_id, offset) {
1142            Status::Ok => Ok(()),
1143            Status::NotFound => Err(Status::NotFound),
1144            Status::BadArgument => Err(Status::BadArgument),
1145            status => panic!("unexpected status: {}", status as u32),
1146        }
1147    }
1148}
1149
1150mod utils {
1151    use crate::types::Bytes;
1152    use std::convert::TryFrom;
1153
1154    pub(super) fn serialize_property_path(path: Vec<&str>) -> Bytes {
1155        if path.is_empty() {
1156            return Vec::new();
1157        }
1158        let mut size: usize = 0;
1159        for part in &path {
1160            size += part.len() + 1;
1161        }
1162        let mut bytes: Bytes = Vec::with_capacity(size);
1163        for part in &path {
1164            bytes.extend_from_slice(part.as_bytes());
1165            bytes.push(0);
1166        }
1167        bytes.pop();
1168        bytes
1169    }
1170
1171    pub(super) fn serialize_map(map: &[(&str, &str)]) -> Bytes {
1172        let mut size: usize = 4;
1173        for (name, value) in map {
1174            size += name.len() + value.len() + 10;
1175        }
1176        let mut bytes: Bytes = Vec::with_capacity(size);
1177        bytes.extend_from_slice(&(map.len() as u32).to_le_bytes());
1178        for (name, value) in map {
1179            bytes.extend_from_slice(&(name.len() as u32).to_le_bytes());
1180            bytes.extend_from_slice(&(value.len() as u32).to_le_bytes());
1181        }
1182        for (name, value) in map {
1183            bytes.extend_from_slice(name.as_bytes());
1184            bytes.push(0);
1185            bytes.extend_from_slice(value.as_bytes());
1186            bytes.push(0);
1187        }
1188        bytes
1189    }
1190
1191    pub(super) fn serialize_map_bytes(map: &[(&str, &[u8])]) -> Bytes {
1192        let mut size: usize = 4;
1193        for (name, value) in map {
1194            size += name.len() + value.len() + 10;
1195        }
1196        let mut bytes: Bytes = Vec::with_capacity(size);
1197        bytes.extend_from_slice(&(map.len() as u32).to_le_bytes());
1198        for (name, value) in map {
1199            bytes.extend_from_slice(&(name.len() as u32).to_le_bytes());
1200            bytes.extend_from_slice(&(value.len() as u32).to_le_bytes());
1201        }
1202        for (name, value) in map {
1203            bytes.extend_from_slice(name.as_bytes());
1204            bytes.push(0);
1205            bytes.extend_from_slice(value);
1206            bytes.push(0);
1207        }
1208        bytes
1209    }
1210
1211    pub(super) fn deserialize_map(bytes: &[u8]) -> Vec<(String, String)> {
1212        if bytes.is_empty() {
1213            return Vec::new();
1214        }
1215        let size = u32::from_le_bytes(<[u8; 4]>::try_from(&bytes[0..4]).unwrap()) as usize;
1216        let mut map = Vec::with_capacity(size);
1217        let mut p = 4 + size * 8;
1218        for n in 0..size {
1219            let s = 4 + n * 8;
1220            let size = u32::from_le_bytes(<[u8; 4]>::try_from(&bytes[s..s + 4]).unwrap()) as usize;
1221            let key = bytes[p..p + size].to_vec();
1222            p += size + 1;
1223            let size =
1224                u32::from_le_bytes(<[u8; 4]>::try_from(&bytes[s + 4..s + 8]).unwrap()) as usize;
1225            let value = bytes[p..p + size].to_vec();
1226            p += size + 1;
1227            map.push((
1228                String::from_utf8(key).unwrap(),
1229                String::from_utf8(value).unwrap(),
1230            ));
1231        }
1232        map
1233    }
1234
1235    pub(super) fn deserialize_map_bytes(bytes: &[u8]) -> Vec<(String, Bytes)> {
1236        if bytes.is_empty() {
1237            return Vec::new();
1238        }
1239        let size = u32::from_le_bytes(<[u8; 4]>::try_from(&bytes[0..4]).unwrap()) as usize;
1240        let mut map = Vec::with_capacity(size);
1241        let mut p = 4 + size * 8;
1242        for n in 0..size {
1243            let s = 4 + n * 8;
1244            let size = u32::from_le_bytes(<[u8; 4]>::try_from(&bytes[s..s + 4]).unwrap()) as usize;
1245            let key = bytes[p..p + size].to_vec();
1246            p += size + 1;
1247            let size =
1248                u32::from_le_bytes(<[u8; 4]>::try_from(&bytes[s + 4..s + 8]).unwrap()) as usize;
1249            let value = bytes[p..p + size].to_vec();
1250            p += size + 1;
1251            map.push((String::from_utf8(key).unwrap(), value));
1252        }
1253        map
1254    }
1255
1256    #[cfg(test)]
1257    mod tests {
1258        use super::*;
1259
1260        #[cfg(nightly)]
1261        use test::Bencher;
1262
1263        static MAP: &[(&str, &str)] = &[
1264            (":method", "GET"),
1265            (":path", "/bytes/1"),
1266            (":authority", "httpbin.org"),
1267            ("Powered-By", "proxy-wasm"),
1268        ];
1269
1270        #[rustfmt::skip]
1271        static SERIALIZED_MAP: &[u8] = &[
1272            // num entries
1273            4, 0, 0, 0,
1274            // len (":method", "GET")
1275            7, 0, 0, 0, 3, 0, 0, 0,
1276            // len (":path", "/bytes/1")
1277            5, 0, 0, 0, 8, 0, 0, 0,
1278            // len (":authority", "httpbin.org")
1279            10, 0, 0, 0, 11, 0, 0, 0,
1280            // len ("Powered-By", "proxy-wasm")
1281            10, 0, 0, 0, 10, 0, 0, 0,
1282            // ":method"
1283            58, 109, 101, 116, 104, 111, 100, 0,
1284            // "GET"
1285            71, 69, 84, 0,
1286            // ":path"
1287            58, 112, 97, 116, 104, 0,
1288            // "/bytes/1"
1289            47, 98, 121, 116, 101, 115, 47, 49, 0,
1290            // ":authority"
1291            58, 97, 117, 116, 104, 111, 114, 105, 116, 121, 0,
1292            // "httpbin.org"
1293            104, 116, 116, 112, 98, 105, 110, 46, 111, 114, 103, 0,
1294            // "Powered-By"
1295            80, 111, 119, 101, 114, 101, 100, 45, 66, 121, 0,
1296            // "proxy-wasm"
1297            112, 114, 111, 120, 121, 45, 119, 97, 115, 109, 0,
1298        ];
1299
1300        #[test]
1301        fn test_serialize_map_empty() {
1302            let serialized_map = serialize_map(&[]);
1303            assert_eq!(serialized_map, [0, 0, 0, 0]);
1304        }
1305
1306        #[test]
1307        fn test_serialize_map_empty_bytes() {
1308            let serialized_map = serialize_map_bytes(&[]);
1309            assert_eq!(serialized_map, [0, 0, 0, 0]);
1310        }
1311
1312        #[test]
1313        fn test_deserialize_map_empty() {
1314            let map = deserialize_map(&[]);
1315            assert_eq!(map, []);
1316            let map = deserialize_map(&[0, 0, 0, 0]);
1317            assert_eq!(map, []);
1318        }
1319
1320        #[test]
1321        fn test_deserialize_map_empty_bytes() {
1322            let map = deserialize_map_bytes(&[]);
1323            assert_eq!(map, []);
1324            let map = deserialize_map_bytes(&[0, 0, 0, 0]);
1325            assert_eq!(map, []);
1326        }
1327
1328        #[test]
1329        fn test_serialize_map() {
1330            let serialized_map = serialize_map(MAP);
1331            assert_eq!(serialized_map, SERIALIZED_MAP);
1332        }
1333
1334        #[test]
1335        fn test_serialize_map_bytes() {
1336            let map: Vec<(&str, &[u8])> = MAP.iter().map(|x| (x.0, x.1.as_bytes())).collect();
1337            let serialized_map = serialize_map_bytes(&map);
1338            assert_eq!(serialized_map, SERIALIZED_MAP);
1339        }
1340
1341        #[test]
1342        fn test_deserialize_map() {
1343            let map = deserialize_map(SERIALIZED_MAP);
1344            assert_eq!(map.len(), MAP.len());
1345            for (got, expected) in map.into_iter().zip(MAP) {
1346                assert_eq!(got.0, expected.0);
1347                assert_eq!(got.1, expected.1);
1348            }
1349        }
1350
1351        #[test]
1352        fn test_deserialize_map_bytes() {
1353            let map = deserialize_map_bytes(SERIALIZED_MAP);
1354            assert_eq!(map.len(), MAP.len());
1355            for (got, expected) in map.into_iter().zip(MAP) {
1356                assert_eq!(got.0, expected.0);
1357                assert_eq!(got.1, expected.1.as_bytes());
1358            }
1359        }
1360
1361        #[test]
1362        fn test_deserialize_map_roundtrip() {
1363            let map = deserialize_map(SERIALIZED_MAP);
1364            // TODO(v0.3): fix arguments, so that maps can be reused without conversion.
1365            let map_refs: Vec<(&str, &str)> =
1366                map.iter().map(|x| (x.0.as_ref(), x.1.as_ref())).collect();
1367            let serialized_map = serialize_map(&map_refs);
1368            assert_eq!(serialized_map, SERIALIZED_MAP);
1369        }
1370
1371        #[test]
1372        fn test_deserialize_map_roundtrip_bytes() {
1373            let map = deserialize_map_bytes(SERIALIZED_MAP);
1374            // TODO(v0.3): fix arguments, so that maps can be reused without conversion.
1375            let map_refs: Vec<(&str, &[u8])> =
1376                map.iter().map(|x| (x.0.as_ref(), x.1.as_ref())).collect();
1377            let serialized_map = serialize_map_bytes(&map_refs);
1378            assert_eq!(serialized_map, SERIALIZED_MAP);
1379        }
1380
1381        #[test]
1382        fn test_deserialize_map_all_chars() {
1383            // 0x00-0x7f are valid single-byte UTF-8 characters.
1384            for i in 0..0x7f {
1385                let serialized_src = [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 99, 0, i, 0];
1386                let map = deserialize_map(&serialized_src);
1387                // TODO(v0.3): fix arguments, so that maps can be reused without conversion.
1388                let map_refs: Vec<(&str, &str)> =
1389                    map.iter().map(|x| (x.0.as_ref(), x.1.as_ref())).collect();
1390                let serialized_map = serialize_map(&map_refs);
1391                assert_eq!(serialized_map, serialized_src);
1392            }
1393            // 0x80-0xff are invalid single-byte UTF-8 characters.
1394            for i in 0x80..0xff {
1395                let serialized_src = [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 99, 0, i, 0];
1396                std::panic::set_hook(Box::new(|_| {}));
1397                let result = std::panic::catch_unwind(|| {
1398                    deserialize_map(&serialized_src);
1399                });
1400                assert!(result.is_err());
1401            }
1402        }
1403
1404        #[test]
1405        fn test_deserialize_map_all_chars_bytes() {
1406            // All 256 single-byte characters are allowed when emitting bytes.
1407            for i in 0..0xff {
1408                let serialized_src = [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 99, 0, i, 0];
1409                let map = deserialize_map_bytes(&serialized_src);
1410                // TODO(v0.3): fix arguments, so that maps can be reused without conversion.
1411                let map_refs: Vec<(&str, &[u8])> =
1412                    map.iter().map(|x| (x.0.as_ref(), x.1.as_ref())).collect();
1413                let serialized_map = serialize_map_bytes(&map_refs);
1414                assert_eq!(serialized_map, serialized_src);
1415            }
1416        }
1417
1418        #[cfg(nightly)]
1419        #[bench]
1420        fn bench_serialize_map(b: &mut Bencher) {
1421            let map = MAP.to_vec();
1422            b.iter(|| {
1423                serialize_map(test::black_box(&map));
1424            });
1425        }
1426
1427        #[cfg(nightly)]
1428        #[bench]
1429        fn bench_serialize_map_bytes(b: &mut Bencher) {
1430            let map: Vec<(&str, &[u8])> = MAP.iter().map(|x| (x.0, x.1.as_bytes())).collect();
1431            b.iter(|| {
1432                serialize_map_bytes(test::black_box(&map));
1433            });
1434        }
1435
1436        #[cfg(nightly)]
1437        #[bench]
1438        fn bench_deserialize_map(b: &mut Bencher) {
1439            let serialized_map = SERIALIZED_MAP.to_vec();
1440            b.iter(|| {
1441                deserialize_map(test::black_box(&serialized_map));
1442            });
1443        }
1444
1445        #[cfg(nightly)]
1446        #[bench]
1447        fn bench_deserialize_map_bytes(b: &mut Bencher) {
1448            let serialized_map = SERIALIZED_MAP.to_vec();
1449            b.iter(|| {
1450                deserialize_map_bytes(test::black_box(&serialized_map));
1451            });
1452        }
1453    }
1454}