diff options
| author | zhangchengwei <[email protected]> | 2019-06-12 11:51:21 +0800 |
|---|---|---|
| committer | zhangchengwei <[email protected]> | 2019-06-12 11:51:21 +0800 |
| commit | 36538c5b592a2cae350853da66ed40f93ddb39c7 (patch) | |
| tree | 8b53c0c8002d8afd06909d6b22c292ebc7973bdf | |
创建
361 files changed, 18025 insertions, 0 deletions
diff --git a/bin/Data b/bin/Data new file mode 100644 index 0000000..fe9f03c --- /dev/null +++ b/bin/Data @@ -0,0 +1 @@ +avlsdk3/Data/
\ No newline at end of file diff --git a/bin/Module b/bin/Module new file mode 100644 index 0000000..2619c12 --- /dev/null +++ b/bin/Module @@ -0,0 +1 @@ +avlsdk3/Module/
\ No newline at end of file diff --git a/bin/avlsdk3/AVLSDK.so b/bin/avlsdk3/AVLSDK.so Binary files differnew file mode 100644 index 0000000..28d2a06 --- /dev/null +++ b/bin/avlsdk3/AVLSDK.so diff --git a/bin/avlsdk3/AVLScanner b/bin/avlsdk3/AVLScanner Binary files differnew file mode 100644 index 0000000..167ed68 --- /dev/null +++ b/bin/avlsdk3/AVLScanner diff --git a/bin/avlsdk3/Config/high_scan.ct b/bin/avlsdk3/Config/high_scan.ct Binary files differnew file mode 100644 index 0000000..c0f87c3 --- /dev/null +++ b/bin/avlsdk3/Config/high_scan.ct diff --git a/bin/avlsdk3/Config/high_speed.ct b/bin/avlsdk3/Config/high_speed.ct Binary files differnew file mode 100644 index 0000000..69935c8 --- /dev/null +++ b/bin/avlsdk3/Config/high_speed.ct diff --git a/bin/avlsdk3/Config/low_mem.ct b/bin/avlsdk3/Config/low_mem.ct Binary files differnew file mode 100644 index 0000000..f29e1c7 --- /dev/null +++ b/bin/avlsdk3/Config/low_mem.ct diff --git a/bin/avlsdk3/Data/AVLA0000.IDX b/bin/avlsdk3/Data/AVLA0000.IDX Binary files differnew file mode 100644 index 0000000..de8f8d1 --- /dev/null +++ b/bin/avlsdk3/Data/AVLA0000.IDX diff --git a/bin/avlsdk3/Data/AVLAA000.IDX b/bin/avlsdk3/Data/AVLAA000.IDX Binary files differnew file mode 100644 index 0000000..6526da9 --- /dev/null +++ b/bin/avlsdk3/Data/AVLAA000.IDX diff --git a/bin/avlsdk3/Data/AVLAA001.DAT b/bin/avlsdk3/Data/AVLAA001.DAT Binary files differnew file mode 100644 index 0000000..43ba32c --- /dev/null +++ b/bin/avlsdk3/Data/AVLAA001.DAT diff --git a/bin/avlsdk3/Data/AVLAM000.IDX b/bin/avlsdk3/Data/AVLAM000.IDX Binary files differnew file mode 100644 index 0000000..c44e6d1 --- /dev/null +++ b/bin/avlsdk3/Data/AVLAM000.IDX diff --git a/bin/avlsdk3/Data/AVLAM001.DAT b/bin/avlsdk3/Data/AVLAM001.DAT Binary files differnew file mode 100644 index 0000000..eff4578 --- /dev/null +++ b/bin/avlsdk3/Data/AVLAM001.DAT diff --git a/bin/avlsdk3/Data/AVLB0000.IDX b/bin/avlsdk3/Data/AVLB0000.IDX Binary files differnew file mode 100644 index 0000000..3e75fd1 --- /dev/null +++ b/bin/avlsdk3/Data/AVLB0000.IDX diff --git a/bin/avlsdk3/Data/AVLB0001.DAT b/bin/avlsdk3/Data/AVLB0001.DAT Binary files differnew file mode 100644 index 0000000..dc6f7e6 --- /dev/null +++ b/bin/avlsdk3/Data/AVLB0001.DAT diff --git a/bin/avlsdk3/Data/AVLC0000.IDX b/bin/avlsdk3/Data/AVLC0000.IDX Binary files differnew file mode 100644 index 0000000..d493cba --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0000.IDX diff --git a/bin/avlsdk3/Data/AVLC0001.ABP b/bin/avlsdk3/Data/AVLC0001.ABP Binary files differnew file mode 100644 index 0000000..18293eb --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0001.ABP diff --git a/bin/avlsdk3/Data/AVLC0001.DAT b/bin/avlsdk3/Data/AVLC0001.DAT Binary files differnew file mode 100644 index 0000000..83ac85a --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0001.DAT diff --git a/bin/avlsdk3/Data/AVLC0002.ABP b/bin/avlsdk3/Data/AVLC0002.ABP Binary files differnew file mode 100644 index 0000000..d8a1391 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0002.ABP diff --git a/bin/avlsdk3/Data/AVLC0002.DAT b/bin/avlsdk3/Data/AVLC0002.DAT Binary files differnew file mode 100644 index 0000000..5d83c52 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0002.DAT diff --git a/bin/avlsdk3/Data/AVLC0003.ABP b/bin/avlsdk3/Data/AVLC0003.ABP Binary files differnew file mode 100644 index 0000000..fc72242 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0003.ABP diff --git a/bin/avlsdk3/Data/AVLC0003.DAT b/bin/avlsdk3/Data/AVLC0003.DAT Binary files differnew file mode 100644 index 0000000..f204d50 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0003.DAT diff --git a/bin/avlsdk3/Data/AVLC0004.ABP b/bin/avlsdk3/Data/AVLC0004.ABP Binary files differnew file mode 100644 index 0000000..528f4cb --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0004.ABP diff --git a/bin/avlsdk3/Data/AVLC0004.DAT b/bin/avlsdk3/Data/AVLC0004.DAT Binary files differnew file mode 100644 index 0000000..f69c880 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0004.DAT diff --git a/bin/avlsdk3/Data/AVLC0005.ABP b/bin/avlsdk3/Data/AVLC0005.ABP Binary files differnew file mode 100644 index 0000000..51c88fa --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0005.ABP diff --git a/bin/avlsdk3/Data/AVLC0005.DAT b/bin/avlsdk3/Data/AVLC0005.DAT Binary files differnew file mode 100644 index 0000000..c1d61e8 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0005.DAT diff --git a/bin/avlsdk3/Data/AVLC0006.ABP b/bin/avlsdk3/Data/AVLC0006.ABP Binary files differnew file mode 100644 index 0000000..870d1f1 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0006.ABP diff --git a/bin/avlsdk3/Data/AVLC0006.DAT b/bin/avlsdk3/Data/AVLC0006.DAT Binary files differnew file mode 100644 index 0000000..12fefd8 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0006.DAT diff --git a/bin/avlsdk3/Data/AVLC0007.ABP b/bin/avlsdk3/Data/AVLC0007.ABP Binary files differnew file mode 100644 index 0000000..f70ad89 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0007.ABP diff --git a/bin/avlsdk3/Data/AVLC0007.DAT b/bin/avlsdk3/Data/AVLC0007.DAT Binary files differnew file mode 100644 index 0000000..22feed4 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0007.DAT diff --git a/bin/avlsdk3/Data/AVLC0008.ABP b/bin/avlsdk3/Data/AVLC0008.ABP Binary files differnew file mode 100644 index 0000000..b2005f5 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0008.ABP diff --git a/bin/avlsdk3/Data/AVLC0008.DAT b/bin/avlsdk3/Data/AVLC0008.DAT Binary files differnew file mode 100644 index 0000000..14840ba --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0008.DAT diff --git a/bin/avlsdk3/Data/AVLC0009.ABP b/bin/avlsdk3/Data/AVLC0009.ABP Binary files differnew file mode 100644 index 0000000..4d98747 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0009.ABP diff --git a/bin/avlsdk3/Data/AVLC0009.DAT b/bin/avlsdk3/Data/AVLC0009.DAT Binary files differnew file mode 100644 index 0000000..0f7e931 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0009.DAT diff --git a/bin/avlsdk3/Data/AVLC000A.ABP b/bin/avlsdk3/Data/AVLC000A.ABP Binary files differnew file mode 100644 index 0000000..93ff230 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC000A.ABP diff --git a/bin/avlsdk3/Data/AVLC000A.DAT b/bin/avlsdk3/Data/AVLC000A.DAT Binary files differnew file mode 100644 index 0000000..8860800 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC000A.DAT diff --git a/bin/avlsdk3/Data/AVLC000B.ABP b/bin/avlsdk3/Data/AVLC000B.ABP Binary files differnew file mode 100644 index 0000000..298eede --- /dev/null +++ b/bin/avlsdk3/Data/AVLC000B.ABP diff --git a/bin/avlsdk3/Data/AVLC000B.DAT b/bin/avlsdk3/Data/AVLC000B.DAT Binary files differnew file mode 100644 index 0000000..f173d53 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC000B.DAT diff --git a/bin/avlsdk3/Data/AVLC000C.ABP b/bin/avlsdk3/Data/AVLC000C.ABP Binary files differnew file mode 100644 index 0000000..67c3cdd --- /dev/null +++ b/bin/avlsdk3/Data/AVLC000C.ABP diff --git a/bin/avlsdk3/Data/AVLC000C.DAT b/bin/avlsdk3/Data/AVLC000C.DAT Binary files differnew file mode 100644 index 0000000..2d195ef --- /dev/null +++ b/bin/avlsdk3/Data/AVLC000C.DAT diff --git a/bin/avlsdk3/Data/AVLC000D.ABP b/bin/avlsdk3/Data/AVLC000D.ABP Binary files differnew file mode 100644 index 0000000..5060cb5 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC000D.ABP diff --git a/bin/avlsdk3/Data/AVLC000D.DAT b/bin/avlsdk3/Data/AVLC000D.DAT Binary files differnew file mode 100644 index 0000000..588b701 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC000D.DAT diff --git a/bin/avlsdk3/Data/AVLC000E.ABP b/bin/avlsdk3/Data/AVLC000E.ABP Binary files differnew file mode 100644 index 0000000..c70855e --- /dev/null +++ b/bin/avlsdk3/Data/AVLC000E.ABP diff --git a/bin/avlsdk3/Data/AVLC000E.DAT b/bin/avlsdk3/Data/AVLC000E.DAT Binary files differnew file mode 100644 index 0000000..3dcd46b --- /dev/null +++ b/bin/avlsdk3/Data/AVLC000E.DAT diff --git a/bin/avlsdk3/Data/AVLC000F.ABP b/bin/avlsdk3/Data/AVLC000F.ABP Binary files differnew file mode 100644 index 0000000..3747ba4 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC000F.ABP diff --git a/bin/avlsdk3/Data/AVLC000F.DAT b/bin/avlsdk3/Data/AVLC000F.DAT Binary files differnew file mode 100644 index 0000000..d766ce5 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC000F.DAT diff --git a/bin/avlsdk3/Data/AVLC0010.ABP b/bin/avlsdk3/Data/AVLC0010.ABP Binary files differnew file mode 100644 index 0000000..cd49784 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0010.ABP diff --git a/bin/avlsdk3/Data/AVLC0010.DAT b/bin/avlsdk3/Data/AVLC0010.DAT Binary files differnew file mode 100644 index 0000000..f348feb --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0010.DAT diff --git a/bin/avlsdk3/Data/AVLC0011.ABP b/bin/avlsdk3/Data/AVLC0011.ABP Binary files differnew file mode 100644 index 0000000..de781a7 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0011.ABP diff --git a/bin/avlsdk3/Data/AVLC0011.DAT b/bin/avlsdk3/Data/AVLC0011.DAT Binary files differnew file mode 100644 index 0000000..e85da52 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0011.DAT diff --git a/bin/avlsdk3/Data/AVLC0012.ABP b/bin/avlsdk3/Data/AVLC0012.ABP Binary files differnew file mode 100644 index 0000000..8a0d074 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0012.ABP diff --git a/bin/avlsdk3/Data/AVLC0012.DAT b/bin/avlsdk3/Data/AVLC0012.DAT Binary files differnew file mode 100644 index 0000000..f836bf8 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0012.DAT diff --git a/bin/avlsdk3/Data/AVLC0013.ABP b/bin/avlsdk3/Data/AVLC0013.ABP Binary files differnew file mode 100644 index 0000000..d6830b3 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0013.ABP diff --git a/bin/avlsdk3/Data/AVLC0013.DAT b/bin/avlsdk3/Data/AVLC0013.DAT Binary files differnew file mode 100644 index 0000000..0f9ab92 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0013.DAT diff --git a/bin/avlsdk3/Data/AVLC0014.ABP b/bin/avlsdk3/Data/AVLC0014.ABP Binary files differnew file mode 100644 index 0000000..113ea21 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0014.ABP diff --git a/bin/avlsdk3/Data/AVLC0014.DAT b/bin/avlsdk3/Data/AVLC0014.DAT Binary files differnew file mode 100644 index 0000000..0dbab9c --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0014.DAT diff --git a/bin/avlsdk3/Data/AVLC0015.ABP b/bin/avlsdk3/Data/AVLC0015.ABP Binary files differnew file mode 100644 index 0000000..8f96ea2 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0015.ABP diff --git a/bin/avlsdk3/Data/AVLC0015.DAT b/bin/avlsdk3/Data/AVLC0015.DAT Binary files differnew file mode 100644 index 0000000..e0e7d36 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0015.DAT diff --git a/bin/avlsdk3/Data/AVLC0016.ABP b/bin/avlsdk3/Data/AVLC0016.ABP Binary files differnew file mode 100644 index 0000000..70ea3eb --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0016.ABP diff --git a/bin/avlsdk3/Data/AVLC0016.DAT b/bin/avlsdk3/Data/AVLC0016.DAT Binary files differnew file mode 100644 index 0000000..b52d43a --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0016.DAT diff --git a/bin/avlsdk3/Data/AVLC0017.ABP b/bin/avlsdk3/Data/AVLC0017.ABP Binary files differnew file mode 100644 index 0000000..3d0fa07 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0017.ABP diff --git a/bin/avlsdk3/Data/AVLC0017.DAT b/bin/avlsdk3/Data/AVLC0017.DAT Binary files differnew file mode 100644 index 0000000..56772bb --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0017.DAT diff --git a/bin/avlsdk3/Data/AVLC0018.ABP b/bin/avlsdk3/Data/AVLC0018.ABP Binary files differnew file mode 100644 index 0000000..c84b222 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0018.ABP diff --git a/bin/avlsdk3/Data/AVLC0018.DAT b/bin/avlsdk3/Data/AVLC0018.DAT Binary files differnew file mode 100644 index 0000000..859987b --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0018.DAT diff --git a/bin/avlsdk3/Data/AVLC0019.ABP b/bin/avlsdk3/Data/AVLC0019.ABP Binary files differnew file mode 100644 index 0000000..b84ef51 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0019.ABP diff --git a/bin/avlsdk3/Data/AVLC0019.DAT b/bin/avlsdk3/Data/AVLC0019.DAT Binary files differnew file mode 100644 index 0000000..c65e92b --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0019.DAT diff --git a/bin/avlsdk3/Data/AVLC001A.ABP b/bin/avlsdk3/Data/AVLC001A.ABP Binary files differnew file mode 100644 index 0000000..ce8d5a5 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC001A.ABP diff --git a/bin/avlsdk3/Data/AVLC001A.DAT b/bin/avlsdk3/Data/AVLC001A.DAT Binary files differnew file mode 100644 index 0000000..474c0ef --- /dev/null +++ b/bin/avlsdk3/Data/AVLC001A.DAT diff --git a/bin/avlsdk3/Data/AVLC001B.ABP b/bin/avlsdk3/Data/AVLC001B.ABP Binary files differnew file mode 100644 index 0000000..6a9555b --- /dev/null +++ b/bin/avlsdk3/Data/AVLC001B.ABP diff --git a/bin/avlsdk3/Data/AVLC001B.DAT b/bin/avlsdk3/Data/AVLC001B.DAT Binary files differnew file mode 100644 index 0000000..b43b1b5 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC001B.DAT diff --git a/bin/avlsdk3/Data/AVLC001C.ABP b/bin/avlsdk3/Data/AVLC001C.ABP Binary files differnew file mode 100644 index 0000000..23f8c32 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC001C.ABP diff --git a/bin/avlsdk3/Data/AVLC001C.DAT b/bin/avlsdk3/Data/AVLC001C.DAT Binary files differnew file mode 100644 index 0000000..a84aa20 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC001C.DAT diff --git a/bin/avlsdk3/Data/AVLC001D.ABP b/bin/avlsdk3/Data/AVLC001D.ABP Binary files differnew file mode 100644 index 0000000..0a45fc7 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC001D.ABP diff --git a/bin/avlsdk3/Data/AVLC001D.DAT b/bin/avlsdk3/Data/AVLC001D.DAT Binary files differnew file mode 100644 index 0000000..40fad19 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC001D.DAT diff --git a/bin/avlsdk3/Data/AVLC001E.ABP b/bin/avlsdk3/Data/AVLC001E.ABP Binary files differnew file mode 100644 index 0000000..af2e758 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC001E.ABP diff --git a/bin/avlsdk3/Data/AVLC001E.DAT b/bin/avlsdk3/Data/AVLC001E.DAT Binary files differnew file mode 100644 index 0000000..ad015bf --- /dev/null +++ b/bin/avlsdk3/Data/AVLC001E.DAT diff --git a/bin/avlsdk3/Data/AVLC001F.ABP b/bin/avlsdk3/Data/AVLC001F.ABP Binary files differnew file mode 100644 index 0000000..07bf4e1 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC001F.ABP diff --git a/bin/avlsdk3/Data/AVLC001F.DAT b/bin/avlsdk3/Data/AVLC001F.DAT Binary files differnew file mode 100644 index 0000000..a24665b --- /dev/null +++ b/bin/avlsdk3/Data/AVLC001F.DAT diff --git a/bin/avlsdk3/Data/AVLC0020.ABP b/bin/avlsdk3/Data/AVLC0020.ABP Binary files differnew file mode 100644 index 0000000..509508d --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0020.ABP diff --git a/bin/avlsdk3/Data/AVLC0020.DAT b/bin/avlsdk3/Data/AVLC0020.DAT Binary files differnew file mode 100644 index 0000000..312173b --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0020.DAT diff --git a/bin/avlsdk3/Data/AVLC0021.ABP b/bin/avlsdk3/Data/AVLC0021.ABP Binary files differnew file mode 100644 index 0000000..f2ce731 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0021.ABP diff --git a/bin/avlsdk3/Data/AVLC0021.DAT b/bin/avlsdk3/Data/AVLC0021.DAT Binary files differnew file mode 100644 index 0000000..17de127 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0021.DAT diff --git a/bin/avlsdk3/Data/AVLC0022.ABP b/bin/avlsdk3/Data/AVLC0022.ABP Binary files differnew file mode 100644 index 0000000..f2ae0ab --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0022.ABP diff --git a/bin/avlsdk3/Data/AVLC0022.DAT b/bin/avlsdk3/Data/AVLC0022.DAT Binary files differnew file mode 100644 index 0000000..67cbbf2 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0022.DAT diff --git a/bin/avlsdk3/Data/AVLC0023.ABP b/bin/avlsdk3/Data/AVLC0023.ABP Binary files differnew file mode 100644 index 0000000..0eee749 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0023.ABP diff --git a/bin/avlsdk3/Data/AVLC0023.DAT b/bin/avlsdk3/Data/AVLC0023.DAT Binary files differnew file mode 100644 index 0000000..f2d8e73 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0023.DAT diff --git a/bin/avlsdk3/Data/AVLC0024.ABP b/bin/avlsdk3/Data/AVLC0024.ABP Binary files differnew file mode 100644 index 0000000..461eec6 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0024.ABP diff --git a/bin/avlsdk3/Data/AVLC0024.DAT b/bin/avlsdk3/Data/AVLC0024.DAT Binary files differnew file mode 100644 index 0000000..9f16b90 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0024.DAT diff --git a/bin/avlsdk3/Data/AVLC0025.ABP b/bin/avlsdk3/Data/AVLC0025.ABP Binary files differnew file mode 100644 index 0000000..7c6646a --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0025.ABP diff --git a/bin/avlsdk3/Data/AVLC0025.DAT b/bin/avlsdk3/Data/AVLC0025.DAT Binary files differnew file mode 100644 index 0000000..1433f26 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0025.DAT diff --git a/bin/avlsdk3/Data/AVLC0026.ABP b/bin/avlsdk3/Data/AVLC0026.ABP Binary files differnew file mode 100644 index 0000000..65f5aa3 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0026.ABP diff --git a/bin/avlsdk3/Data/AVLC0026.DAT b/bin/avlsdk3/Data/AVLC0026.DAT Binary files differnew file mode 100644 index 0000000..b829edc --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0026.DAT diff --git a/bin/avlsdk3/Data/AVLC0027.ABP b/bin/avlsdk3/Data/AVLC0027.ABP Binary files differnew file mode 100644 index 0000000..ba0924a --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0027.ABP diff --git a/bin/avlsdk3/Data/AVLC0027.DAT b/bin/avlsdk3/Data/AVLC0027.DAT Binary files differnew file mode 100644 index 0000000..049d80b --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0027.DAT diff --git a/bin/avlsdk3/Data/AVLC0028.ABP b/bin/avlsdk3/Data/AVLC0028.ABP Binary files differnew file mode 100644 index 0000000..ccf0a25 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0028.ABP diff --git a/bin/avlsdk3/Data/AVLC0028.DAT b/bin/avlsdk3/Data/AVLC0028.DAT Binary files differnew file mode 100644 index 0000000..3ba7376 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0028.DAT diff --git a/bin/avlsdk3/Data/AVLC0029.ABP b/bin/avlsdk3/Data/AVLC0029.ABP Binary files differnew file mode 100644 index 0000000..ddcbcb7 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0029.ABP diff --git a/bin/avlsdk3/Data/AVLC0029.DAT b/bin/avlsdk3/Data/AVLC0029.DAT Binary files differnew file mode 100644 index 0000000..cedbf97 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC0029.DAT diff --git a/bin/avlsdk3/Data/AVLC002A.ABP b/bin/avlsdk3/Data/AVLC002A.ABP new file mode 100644 index 0000000..4f6433c --- /dev/null +++ b/bin/avlsdk3/Data/AVLC002A.ABP @@ -0,0 +1,2 @@ +AVL3��C`
��j�sN#��l��`<s�d�
`U�Zdyj<t���˔�*w�6�"9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���c�ĵ�U�4B�%�>�&��n�F�����Ā���:U�� +SDw�!OX(��e)N��'%�*.�|Me�b:M�r,�&L-9u1MIm2�TV#4.���9u1MIm2�TV#4.����Za�.0��:�s�����j��C�;Z�aʃE1�N8.f꘡��=L�d��1��4���B�Wm�¡�Ɩ7-�C�Nf�8
\ No newline at end of file diff --git a/bin/avlsdk3/Data/AVLC002A.DAT b/bin/avlsdk3/Data/AVLC002A.DAT Binary files differnew file mode 100644 index 0000000..2071083 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC002A.DAT diff --git a/bin/avlsdk3/Data/AVLC002B.ABP b/bin/avlsdk3/Data/AVLC002B.ABP Binary files differnew file mode 100644 index 0000000..1675e34 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC002B.ABP diff --git a/bin/avlsdk3/Data/AVLC002B.DAT b/bin/avlsdk3/Data/AVLC002B.DAT Binary files differnew file mode 100644 index 0000000..9e941b7 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC002B.DAT diff --git a/bin/avlsdk3/Data/AVLC002C.ABP b/bin/avlsdk3/Data/AVLC002C.ABP new file mode 100644 index 0000000..cd2c00f --- /dev/null +++ b/bin/avlsdk3/Data/AVLC002C.ABP @@ -0,0 +1,2 @@ +AVL3��3(_����9���'�X����Y��Q��n<t���˔�*w�6�"9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���c�ĵ�U�4B�%�>�&cQ�p�V*�8�����b�4�u��?���4�AK��{2&���
U�l�������TϜ��;9u1MIm2�TV#4.��ʷ&�<,+ �zm���x�'v�2���4�NX����]�1l��9my����
�N���:����B���������� +���Է��"�l��
\ No newline at end of file diff --git a/bin/avlsdk3/Data/AVLC002C.DAT b/bin/avlsdk3/Data/AVLC002C.DAT Binary files differnew file mode 100644 index 0000000..0676703 --- /dev/null +++ b/bin/avlsdk3/Data/AVLC002C.DAT diff --git a/bin/avlsdk3/Data/AVLD0000.IDX b/bin/avlsdk3/Data/AVLD0000.IDX Binary files differnew file mode 100644 index 0000000..6672fea --- /dev/null +++ b/bin/avlsdk3/Data/AVLD0000.IDX diff --git a/bin/avlsdk3/Data/AVLD0001.DAT b/bin/avlsdk3/Data/AVLD0001.DAT Binary files differnew file mode 100644 index 0000000..ee81c9e --- /dev/null +++ b/bin/avlsdk3/Data/AVLD0001.DAT diff --git a/bin/avlsdk3/Data/AVLFB000.IDX b/bin/avlsdk3/Data/AVLFB000.IDX Binary files differnew file mode 100644 index 0000000..36b1c71 --- /dev/null +++ b/bin/avlsdk3/Data/AVLFB000.IDX diff --git a/bin/avlsdk3/Data/AVLFB001.DAT b/bin/avlsdk3/Data/AVLFB001.DAT Binary files differnew file mode 100644 index 0000000..7c4761a --- /dev/null +++ b/bin/avlsdk3/Data/AVLFB001.DAT diff --git a/bin/avlsdk3/Data/AVLFM000.IDX b/bin/avlsdk3/Data/AVLFM000.IDX Binary files differnew file mode 100644 index 0000000..86bb970 --- /dev/null +++ b/bin/avlsdk3/Data/AVLFM000.IDX diff --git a/bin/avlsdk3/Data/AVLFM001.DAT b/bin/avlsdk3/Data/AVLFM001.DAT Binary files differnew file mode 100644 index 0000000..6518d4c --- /dev/null +++ b/bin/avlsdk3/Data/AVLFM001.DAT diff --git a/bin/avlsdk3/Data/AVLH0000.IDX b/bin/avlsdk3/Data/AVLH0000.IDX Binary files differnew file mode 100644 index 0000000..359ec3e --- /dev/null +++ b/bin/avlsdk3/Data/AVLH0000.IDX diff --git a/bin/avlsdk3/Data/AVLH0001.ABP b/bin/avlsdk3/Data/AVLH0001.ABP Binary files differnew file mode 100644 index 0000000..b02951f --- /dev/null +++ b/bin/avlsdk3/Data/AVLH0001.ABP diff --git a/bin/avlsdk3/Data/AVLH0001.DAT b/bin/avlsdk3/Data/AVLH0001.DAT Binary files differnew file mode 100644 index 0000000..b435dc7 --- /dev/null +++ b/bin/avlsdk3/Data/AVLH0001.DAT diff --git a/bin/avlsdk3/Data/AVLH0002.ABP b/bin/avlsdk3/Data/AVLH0002.ABP Binary files differnew file mode 100644 index 0000000..c7f9ecf --- /dev/null +++ b/bin/avlsdk3/Data/AVLH0002.ABP diff --git a/bin/avlsdk3/Data/AVLH0002.DAT b/bin/avlsdk3/Data/AVLH0002.DAT Binary files differnew file mode 100644 index 0000000..b55adad --- /dev/null +++ b/bin/avlsdk3/Data/AVLH0002.DAT diff --git a/bin/avlsdk3/Data/AVLH0003.ABP b/bin/avlsdk3/Data/AVLH0003.ABP Binary files differnew file mode 100644 index 0000000..0732692 --- /dev/null +++ b/bin/avlsdk3/Data/AVLH0003.ABP diff --git a/bin/avlsdk3/Data/AVLH0003.DAT b/bin/avlsdk3/Data/AVLH0003.DAT Binary files differnew file mode 100644 index 0000000..c540ad9 --- /dev/null +++ b/bin/avlsdk3/Data/AVLH0003.DAT diff --git a/bin/avlsdk3/Data/AVLHT000.IDX b/bin/avlsdk3/Data/AVLHT000.IDX new file mode 100644 index 0000000..68ab301 --- /dev/null +++ b/bin/avlsdk3/Data/AVLHT000.IDX @@ -0,0 +1,6 @@ +AVL3wD7��[B)��pm�h���i�dB�����w�j +���@��;<蹾�9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���c�ĵ�U�4B�%�>�&������+3�?>N�-xzf��&�����a͑(�̋!c��/�?8�!j�'�*�������Y�ɥ5�6�d;U��3 ہ�)�(�gF�Mא#�>�H� +�����bܢ�#���ם�`ˁ� :��[�Ă}��2�"�pm�Q��є-�=G�r.y�Y{�mK�~������?4�t[5:�N��0��u�V� +��۫��&/1"�FJqi�5s�W���)���3��TH��7���X�~œ���%�GM�`�md����+��C��T�:�x�i!�
.;�Z>�̀� 5⑅���JR��He�Ht* +�x\��I�V��%��Qa�ɐ=H���b��l +̀s4o
��b���j����>t]�C1���(��s\������
\ No newline at end of file diff --git a/bin/avlsdk3/Data/AVLIB000.IDX b/bin/avlsdk3/Data/AVLIB000.IDX Binary files differnew file mode 100644 index 0000000..1e07032 --- /dev/null +++ b/bin/avlsdk3/Data/AVLIB000.IDX diff --git a/bin/avlsdk3/Data/AVLIB001.DAT b/bin/avlsdk3/Data/AVLIB001.DAT Binary files differnew file mode 100644 index 0000000..627f8ea --- /dev/null +++ b/bin/avlsdk3/Data/AVLIB001.DAT diff --git a/bin/avlsdk3/Data/AVLIM000.IDX b/bin/avlsdk3/Data/AVLIM000.IDX Binary files differnew file mode 100644 index 0000000..5bf96a8 --- /dev/null +++ b/bin/avlsdk3/Data/AVLIM000.IDX diff --git a/bin/avlsdk3/Data/AVLIM001.DAT b/bin/avlsdk3/Data/AVLIM001.DAT Binary files differnew file mode 100644 index 0000000..da94b3e --- /dev/null +++ b/bin/avlsdk3/Data/AVLIM001.DAT diff --git a/bin/avlsdk3/Data/AVLJD000.IDX b/bin/avlsdk3/Data/AVLJD000.IDX Binary files differnew file mode 100644 index 0000000..6abacc8 --- /dev/null +++ b/bin/avlsdk3/Data/AVLJD000.IDX diff --git a/bin/avlsdk3/Data/AVLJD001.DAT b/bin/avlsdk3/Data/AVLJD001.DAT Binary files differnew file mode 100644 index 0000000..77d55d1 --- /dev/null +++ b/bin/avlsdk3/Data/AVLJD001.DAT diff --git a/bin/avlsdk3/Data/AVLK0000.IDX b/bin/avlsdk3/Data/AVLK0000.IDX Binary files differnew file mode 100644 index 0000000..8f30c64 --- /dev/null +++ b/bin/avlsdk3/Data/AVLK0000.IDX diff --git a/bin/avlsdk3/Data/AVLK0001.DAT b/bin/avlsdk3/Data/AVLK0001.DAT Binary files differnew file mode 100644 index 0000000..b4d7451 --- /dev/null +++ b/bin/avlsdk3/Data/AVLK0001.DAT diff --git a/bin/avlsdk3/Data/AVLLB000.IDX b/bin/avlsdk3/Data/AVLLB000.IDX Binary files differnew file mode 100644 index 0000000..3953048 --- /dev/null +++ b/bin/avlsdk3/Data/AVLLB000.IDX diff --git a/bin/avlsdk3/Data/AVLLB001.DAT b/bin/avlsdk3/Data/AVLLB001.DAT Binary files differnew file mode 100644 index 0000000..3a6a506 --- /dev/null +++ b/bin/avlsdk3/Data/AVLLB001.DAT diff --git a/bin/avlsdk3/Data/AVLLC000.IDX b/bin/avlsdk3/Data/AVLLC000.IDX Binary files differnew file mode 100644 index 0000000..ad90266 --- /dev/null +++ b/bin/avlsdk3/Data/AVLLC000.IDX diff --git a/bin/avlsdk3/Data/AVLLM000.IDX b/bin/avlsdk3/Data/AVLLM000.IDX Binary files differnew file mode 100644 index 0000000..888381c --- /dev/null +++ b/bin/avlsdk3/Data/AVLLM000.IDX diff --git a/bin/avlsdk3/Data/AVLLM001.DAT b/bin/avlsdk3/Data/AVLLM001.DAT Binary files differnew file mode 100644 index 0000000..b95f8ee --- /dev/null +++ b/bin/avlsdk3/Data/AVLLM001.DAT diff --git a/bin/avlsdk3/Data/AVLN0000.IDX b/bin/avlsdk3/Data/AVLN0000.IDX Binary files differnew file mode 100644 index 0000000..3ccf322 --- /dev/null +++ b/bin/avlsdk3/Data/AVLN0000.IDX diff --git a/bin/avlsdk3/Data/AVLN0001.ABP b/bin/avlsdk3/Data/AVLN0001.ABP Binary files differnew file mode 100644 index 0000000..80df519 --- /dev/null +++ b/bin/avlsdk3/Data/AVLN0001.ABP diff --git a/bin/avlsdk3/Data/AVLN0001.DAT b/bin/avlsdk3/Data/AVLN0001.DAT Binary files differnew file mode 100644 index 0000000..e09f324 --- /dev/null +++ b/bin/avlsdk3/Data/AVLN0001.DAT diff --git a/bin/avlsdk3/Data/AVLN0002.ABP b/bin/avlsdk3/Data/AVLN0002.ABP Binary files differnew file mode 100644 index 0000000..5069dc2 --- /dev/null +++ b/bin/avlsdk3/Data/AVLN0002.ABP diff --git a/bin/avlsdk3/Data/AVLN0002.DAT b/bin/avlsdk3/Data/AVLN0002.DAT Binary files differnew file mode 100644 index 0000000..0a590db --- /dev/null +++ b/bin/avlsdk3/Data/AVLN0002.DAT diff --git a/bin/avlsdk3/Data/AVLN0003.ABP b/bin/avlsdk3/Data/AVLN0003.ABP Binary files differnew file mode 100644 index 0000000..f0c421b --- /dev/null +++ b/bin/avlsdk3/Data/AVLN0003.ABP diff --git a/bin/avlsdk3/Data/AVLN0003.DAT b/bin/avlsdk3/Data/AVLN0003.DAT Binary files differnew file mode 100644 index 0000000..dca7d8f --- /dev/null +++ b/bin/avlsdk3/Data/AVLN0003.DAT diff --git a/bin/avlsdk3/Data/AVLO0000.IDX b/bin/avlsdk3/Data/AVLO0000.IDX Binary files differnew file mode 100644 index 0000000..9369ac7 --- /dev/null +++ b/bin/avlsdk3/Data/AVLO0000.IDX diff --git a/bin/avlsdk3/Data/AVLO0001.ABP b/bin/avlsdk3/Data/AVLO0001.ABP Binary files differnew file mode 100644 index 0000000..93cd7e5 --- /dev/null +++ b/bin/avlsdk3/Data/AVLO0001.ABP diff --git a/bin/avlsdk3/Data/AVLO0001.DAT b/bin/avlsdk3/Data/AVLO0001.DAT Binary files differnew file mode 100644 index 0000000..76ccabf --- /dev/null +++ b/bin/avlsdk3/Data/AVLO0001.DAT diff --git a/bin/avlsdk3/Data/AVLO0002.ABP b/bin/avlsdk3/Data/AVLO0002.ABP Binary files differnew file mode 100644 index 0000000..e854fde --- /dev/null +++ b/bin/avlsdk3/Data/AVLO0002.ABP diff --git a/bin/avlsdk3/Data/AVLO0002.DAT b/bin/avlsdk3/Data/AVLO0002.DAT Binary files differnew file mode 100644 index 0000000..e731c91 --- /dev/null +++ b/bin/avlsdk3/Data/AVLO0002.DAT diff --git a/bin/avlsdk3/Data/AVLO0003.ABP b/bin/avlsdk3/Data/AVLO0003.ABP new file mode 100644 index 0000000..7b06156 --- /dev/null +++ b/bin/avlsdk3/Data/AVLO0003.ABP @@ -0,0 +1,2 @@ +AVL3�����Dx�L��6��i��i��+�K$��CXE70��L�����|9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���c�ĵ�U�4B�%�>�&6z$G��6lV�|�F0=�=/����_ʑ����;���S�{��q������TIɦ]^GkTn�P���� ��&�-��@�T\���uK��m��o�8'x���~jz� +E��D۬S�#$�&���pkOi�&���dX��0в�HJ7G#U�ni���]����E�Þ��i����x9ag;�V{{F��^�z3t�T!
\ No newline at end of file diff --git a/bin/avlsdk3/Data/AVLO0003.DAT b/bin/avlsdk3/Data/AVLO0003.DAT Binary files differnew file mode 100644 index 0000000..b97b035 --- /dev/null +++ b/bin/avlsdk3/Data/AVLO0003.DAT diff --git a/bin/avlsdk3/Data/AVLP0000.IDX b/bin/avlsdk3/Data/AVLP0000.IDX Binary files differnew file mode 100644 index 0000000..0cb4cd6 --- /dev/null +++ b/bin/avlsdk3/Data/AVLP0000.IDX diff --git a/bin/avlsdk3/Data/AVLQ0000.IDX b/bin/avlsdk3/Data/AVLQ0000.IDX Binary files differnew file mode 100644 index 0000000..205f277 --- /dev/null +++ b/bin/avlsdk3/Data/AVLQ0000.IDX diff --git a/bin/avlsdk3/Data/AVLQ0001.DAT b/bin/avlsdk3/Data/AVLQ0001.DAT Binary files differnew file mode 100644 index 0000000..80ef6d1 --- /dev/null +++ b/bin/avlsdk3/Data/AVLQ0001.DAT diff --git a/bin/avlsdk3/Data/AVLRA000.IDX b/bin/avlsdk3/Data/AVLRA000.IDX Binary files differnew file mode 100644 index 0000000..acea991 --- /dev/null +++ b/bin/avlsdk3/Data/AVLRA000.IDX diff --git a/bin/avlsdk3/Data/AVLRA001.DAT b/bin/avlsdk3/Data/AVLRA001.DAT Binary files differnew file mode 100644 index 0000000..80c895c --- /dev/null +++ b/bin/avlsdk3/Data/AVLRA001.DAT diff --git a/bin/avlsdk3/Data/AVLRB000.IDX b/bin/avlsdk3/Data/AVLRB000.IDX Binary files differnew file mode 100644 index 0000000..a311a9f --- /dev/null +++ b/bin/avlsdk3/Data/AVLRB000.IDX diff --git a/bin/avlsdk3/Data/AVLRB001.DAT b/bin/avlsdk3/Data/AVLRB001.DAT Binary files differnew file mode 100644 index 0000000..027b18c --- /dev/null +++ b/bin/avlsdk3/Data/AVLRB001.DAT diff --git a/bin/avlsdk3/Data/AVLRD000.IDX b/bin/avlsdk3/Data/AVLRD000.IDX Binary files differnew file mode 100644 index 0000000..c1d78f1 --- /dev/null +++ b/bin/avlsdk3/Data/AVLRD000.IDX diff --git a/bin/avlsdk3/Data/AVLRM000.IDX b/bin/avlsdk3/Data/AVLRM000.IDX Binary files differnew file mode 100644 index 0000000..eb6a4db --- /dev/null +++ b/bin/avlsdk3/Data/AVLRM000.IDX diff --git a/bin/avlsdk3/Data/AVLRM001.DAT b/bin/avlsdk3/Data/AVLRM001.DAT Binary files differnew file mode 100644 index 0000000..0cae94d --- /dev/null +++ b/bin/avlsdk3/Data/AVLRM001.DAT diff --git a/bin/avlsdk3/Data/AVLSB000.IDX b/bin/avlsdk3/Data/AVLSB000.IDX new file mode 100644 index 0000000..82669f5 --- /dev/null +++ b/bin/avlsdk3/Data/AVLSB000.IDX @@ -0,0 +1,4 @@ +AVL3��n�`��!�d��T<��A{]?+zT~'���H�߿�8�_�e��wnu9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���c�ĵ�U�4B�%�>�&�
�o�H���,L%`�t���=����T&�D�wo�22(c��T�Ζ�m7���^��P�DB��o�eX�@��}Ğ�@.����ciD%|]0Ǣ�Aլ�ܘ;6|�������H�m��|����~wP�&�9:(�_;ņ���������i'��:�t4�[���(�� +�.��iԉV�ɒ��{L놓
�0R�yE4ܨb��7#���4lh��}��uv;
�7i}�d`��o/XoQ$�S�
k +���4�=���� �e��A�Z>6�2PD",�W�}�M���t�j�g��v.Pndt+�Jk�.B}�崹&O1�R,��7�q�#��G%�K����s��
B���.��p0��.�Np��.4jE�M�m�R�����R���ݞ*Z��D� +�8�4D����1"5~ld=&�l!"���.� /:>Ԛ��"%�y�^�x1n{,�K�R�WW�� �S/��Ӎx� h2P�u�8�g��5-���&x<��B)G%8��0ࠕ;0N�龼cb����)˔|��n�T�?��A�
���(�2+���F���f�#ҳ)e��^�ӂ�Th�g���MI{ n$�����D礯2��2�A%�f���գ��b 1q��U��S�&��a9-
���5 ���/�&4���(�6���jX�Q_<�ݞ��0�s�}���
�ȁ�V���y����"���'"(�T"����ى��gCn�I��s��gA8������2eKfK���� _���9H���Ox�s}
\ No newline at end of file diff --git a/bin/avlsdk3/Data/AVLSB001.ABP b/bin/avlsdk3/Data/AVLSB001.ABP new file mode 100644 index 0000000..86fe6a6 --- /dev/null +++ b/bin/avlsdk3/Data/AVLSB001.ABP @@ -0,0 +1 @@ +AVL3��n�`��!�d��Tٝw��o��ֹD��$<t���˔�*w�6�"9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���c�ĵ�U�4B�%�>�&,�je��'�%ӄzr��7�h���,Z
�n�as9$���<UB���f7�_gT��[m�QB�q�T9u1MIm2�TV#4.���9u1MIm2�TV#4.���+�*�p�
^.��W�W�4�pw�J�PhE$�t����,��^���? |ғK+o��3B�v�4� �D�� r
\ No newline at end of file diff --git a/bin/avlsdk3/Data/AVLSB001.DAT b/bin/avlsdk3/Data/AVLSB001.DAT Binary files differnew file mode 100644 index 0000000..6be036b --- /dev/null +++ b/bin/avlsdk3/Data/AVLSB001.DAT diff --git a/bin/avlsdk3/Data/AVLSB002.ABP b/bin/avlsdk3/Data/AVLSB002.ABP new file mode 100644 index 0000000..f6950b0 --- /dev/null +++ b/bin/avlsdk3/Data/AVLSB002.ABP @@ -0,0 +1 @@ +AVL3��n�`��!�d��Tk�C�f�@� ���xi�<t���˔�*w�6�"9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���c�ĵ�U�4B�%�>�&,�je��'�%ӄzr��7�h���,Z
�n�as9$���<UB���f7�_gT��[m�QB�q�T9u1MIm2�TV#4.���9u1MIm2�TV#4.���+�*�p�
^.��W�W�4�pw�J�PhE$�t����,��^���? |ғK+o��3B�v�4� �D�� r
\ No newline at end of file diff --git a/bin/avlsdk3/Data/AVLSB002.DAT b/bin/avlsdk3/Data/AVLSB002.DAT Binary files differnew file mode 100644 index 0000000..fa80cf4 --- /dev/null +++ b/bin/avlsdk3/Data/AVLSB002.DAT diff --git a/bin/avlsdk3/Data/AVLSB003.ABP b/bin/avlsdk3/Data/AVLSB003.ABP new file mode 100644 index 0000000..4fa6767 --- /dev/null +++ b/bin/avlsdk3/Data/AVLSB003.ABP @@ -0,0 +1,2 @@ +AVL3��n�`��!�d��Ti��i��+�K$��CX<t���˔�*w�6�"9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���c�ĵ�U�4B�%�>�&���@k�O�Z�Pt(-�C��ý;p�!D� +z9(L���5j����>�__M�����x�� 9u1MIm2�TV#4.���9u1MIm2�TV#4.��ʰ��V��J�J��ɟ.O��e�0�E��g�z�sΟ����Q��I)�8ⷙ�[2s����P(��q.n����)��������ʺ�|n1��6��-w�
\ No newline at end of file diff --git a/bin/avlsdk3/Data/AVLSB003.DAT b/bin/avlsdk3/Data/AVLSB003.DAT Binary files differnew file mode 100644 index 0000000..03a4773 --- /dev/null +++ b/bin/avlsdk3/Data/AVLSB003.DAT diff --git a/bin/avlsdk3/Data/AVLSB004.ABP b/bin/avlsdk3/Data/AVLSB004.ABP new file mode 100644 index 0000000..4369ce9 --- /dev/null +++ b/bin/avlsdk3/Data/AVLSB004.ABP @@ -0,0 +1 @@ +AVL3��n�`��!�d��T���ߵ��_�rg]���`��T��@�v�{9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���c�ĵ�U�4B�%�>�&Ǣwo9-�)���*CBJm�\f�h��cs��g�敯�N�佂�� � ��0��~�۲�H痨5qJ6���=���5����Nt��h����ś�?�{���*C5D=Խ�1�N8.f꘡��=L�d��1��4���B�Wm���J�u�cިr�1D��
\ No newline at end of file diff --git a/bin/avlsdk3/Data/AVLSB004.DAT b/bin/avlsdk3/Data/AVLSB004.DAT Binary files differnew file mode 100644 index 0000000..c5ab56c --- /dev/null +++ b/bin/avlsdk3/Data/AVLSB004.DAT diff --git a/bin/avlsdk3/Data/AVLSE000.IDX b/bin/avlsdk3/Data/AVLSE000.IDX Binary files differnew file mode 100644 index 0000000..1ac60c5 --- /dev/null +++ b/bin/avlsdk3/Data/AVLSE000.IDX diff --git a/bin/avlsdk3/Data/AVLSP000.IDX b/bin/avlsdk3/Data/AVLSP000.IDX Binary files differnew file mode 100644 index 0000000..2475a09 --- /dev/null +++ b/bin/avlsdk3/Data/AVLSP000.IDX diff --git a/bin/avlsdk3/Data/AVLSP001.DAT b/bin/avlsdk3/Data/AVLSP001.DAT Binary files differnew file mode 100644 index 0000000..0192162 --- /dev/null +++ b/bin/avlsdk3/Data/AVLSP001.DAT diff --git a/bin/avlsdk3/Data/AVLSS000.IDX b/bin/avlsdk3/Data/AVLSS000.IDX Binary files differnew file mode 100644 index 0000000..820b928 --- /dev/null +++ b/bin/avlsdk3/Data/AVLSS000.IDX diff --git a/bin/avlsdk3/Data/AVLSW000.IDX b/bin/avlsdk3/Data/AVLSW000.IDX Binary files differnew file mode 100644 index 0000000..ec26848 --- /dev/null +++ b/bin/avlsdk3/Data/AVLSW000.IDX diff --git a/bin/avlsdk3/Data/AVLSW001.DAT b/bin/avlsdk3/Data/AVLSW001.DAT Binary files differnew file mode 100644 index 0000000..13b0168 --- /dev/null +++ b/bin/avlsdk3/Data/AVLSW001.DAT diff --git a/bin/avlsdk3/Data/AVLSW002.DAT b/bin/avlsdk3/Data/AVLSW002.DAT Binary files differnew file mode 100644 index 0000000..81c94a8 --- /dev/null +++ b/bin/avlsdk3/Data/AVLSW002.DAT diff --git a/bin/avlsdk3/Data/AVLSX001.ABP b/bin/avlsdk3/Data/AVLSX001.ABP Binary files differnew file mode 100644 index 0000000..c2f2373 --- /dev/null +++ b/bin/avlsdk3/Data/AVLSX001.ABP diff --git a/bin/avlsdk3/Data/AVLSX001.DAT b/bin/avlsdk3/Data/AVLSX001.DAT Binary files differnew file mode 100644 index 0000000..134d842 --- /dev/null +++ b/bin/avlsdk3/Data/AVLSX001.DAT diff --git a/bin/avlsdk3/Data/AVLSX002.ABP b/bin/avlsdk3/Data/AVLSX002.ABP Binary files differnew file mode 100644 index 0000000..600e910 --- /dev/null +++ b/bin/avlsdk3/Data/AVLSX002.ABP diff --git a/bin/avlsdk3/Data/AVLSX002.DAT b/bin/avlsdk3/Data/AVLSX002.DAT Binary files differnew file mode 100644 index 0000000..55743e8 --- /dev/null +++ b/bin/avlsdk3/Data/AVLSX002.DAT diff --git a/bin/avlsdk3/Data/AVLSX003.ABP b/bin/avlsdk3/Data/AVLSX003.ABP Binary files differnew file mode 100644 index 0000000..d702460 --- /dev/null +++ b/bin/avlsdk3/Data/AVLSX003.ABP diff --git a/bin/avlsdk3/Data/AVLSX003.DAT b/bin/avlsdk3/Data/AVLSX003.DAT Binary files differnew file mode 100644 index 0000000..ac59332 --- /dev/null +++ b/bin/avlsdk3/Data/AVLSX003.DAT diff --git a/bin/avlsdk3/Data/AVLSX004.ABP b/bin/avlsdk3/Data/AVLSX004.ABP Binary files differnew file mode 100644 index 0000000..2b8ff04 --- /dev/null +++ b/bin/avlsdk3/Data/AVLSX004.ABP diff --git a/bin/avlsdk3/Data/AVLSX004.DAT b/bin/avlsdk3/Data/AVLSX004.DAT Binary files differnew file mode 100644 index 0000000..a19b050 --- /dev/null +++ b/bin/avlsdk3/Data/AVLSX004.DAT diff --git a/bin/avlsdk3/Data/AVLT0000.IDX b/bin/avlsdk3/Data/AVLT0000.IDX Binary files differnew file mode 100644 index 0000000..7b39fb8 --- /dev/null +++ b/bin/avlsdk3/Data/AVLT0000.IDX diff --git a/bin/avlsdk3/Data/AVLT0001.ABP b/bin/avlsdk3/Data/AVLT0001.ABP Binary files differnew file mode 100644 index 0000000..273d1bd --- /dev/null +++ b/bin/avlsdk3/Data/AVLT0001.ABP diff --git a/bin/avlsdk3/Data/AVLT0001.DAT b/bin/avlsdk3/Data/AVLT0001.DAT Binary files differnew file mode 100644 index 0000000..7bedf5f --- /dev/null +++ b/bin/avlsdk3/Data/AVLT0001.DAT diff --git a/bin/avlsdk3/Data/AVLU0000.IDX b/bin/avlsdk3/Data/AVLU0000.IDX Binary files differnew file mode 100644 index 0000000..2e8bacf --- /dev/null +++ b/bin/avlsdk3/Data/AVLU0000.IDX diff --git a/bin/avlsdk3/Data/AVLV0000.IDX b/bin/avlsdk3/Data/AVLV0000.IDX Binary files differnew file mode 100644 index 0000000..866551d --- /dev/null +++ b/bin/avlsdk3/Data/AVLV0000.IDX diff --git a/bin/avlsdk3/Data/AVLV0001.DAT b/bin/avlsdk3/Data/AVLV0001.DAT Binary files differnew file mode 100644 index 0000000..3f5788e --- /dev/null +++ b/bin/avlsdk3/Data/AVLV0001.DAT diff --git a/bin/avlsdk3/Data/AVLW0000.IDX b/bin/avlsdk3/Data/AVLW0000.IDX Binary files differnew file mode 100644 index 0000000..0a00e46 --- /dev/null +++ b/bin/avlsdk3/Data/AVLW0000.IDX diff --git a/bin/avlsdk3/Data/AVLW0001.ABP b/bin/avlsdk3/Data/AVLW0001.ABP Binary files differnew file mode 100644 index 0000000..3dd2ff7 --- /dev/null +++ b/bin/avlsdk3/Data/AVLW0001.ABP diff --git a/bin/avlsdk3/Data/AVLW0001.DAT b/bin/avlsdk3/Data/AVLW0001.DAT Binary files differnew file mode 100644 index 0000000..71c76d4 --- /dev/null +++ b/bin/avlsdk3/Data/AVLW0001.DAT diff --git a/bin/avlsdk3/Data/AVLWD000.IDX b/bin/avlsdk3/Data/AVLWD000.IDX Binary files differnew file mode 100644 index 0000000..4d986d2 --- /dev/null +++ b/bin/avlsdk3/Data/AVLWD000.IDX diff --git a/bin/avlsdk3/Data/AVLWD001.DAT b/bin/avlsdk3/Data/AVLWD001.DAT Binary files differnew file mode 100644 index 0000000..c3cb021 --- /dev/null +++ b/bin/avlsdk3/Data/AVLWD001.DAT diff --git a/bin/avlsdk3/Data/AVLWG000.IDX b/bin/avlsdk3/Data/AVLWG000.IDX Binary files differnew file mode 100644 index 0000000..ffcd2cb --- /dev/null +++ b/bin/avlsdk3/Data/AVLWG000.IDX diff --git a/bin/avlsdk3/Data/AVLWG001.DAT b/bin/avlsdk3/Data/AVLWG001.DAT Binary files differnew file mode 100644 index 0000000..5ffb998 --- /dev/null +++ b/bin/avlsdk3/Data/AVLWG001.DAT diff --git a/bin/avlsdk3/Data/AVLWS000.IDX b/bin/avlsdk3/Data/AVLWS000.IDX Binary files differnew file mode 100644 index 0000000..021a30e --- /dev/null +++ b/bin/avlsdk3/Data/AVLWS000.IDX diff --git a/bin/avlsdk3/Data/AVLX0001.DAT b/bin/avlsdk3/Data/AVLX0001.DAT new file mode 100644 index 0000000..bb7f205 --- /dev/null +++ b/bin/avlsdk3/Data/AVLX0001.DAT @@ -0,0 +1 @@ +AVL3�lG#�3Lԝ�
����jBe��.�ݎ�8 tg)���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���9u1MIm2�TV#4.���c�ĵ�U�4B�%�>�&
��Nҝ�7�L-p
��]�`�ĺ�b�S/}@��m���}-%�%#�6.�E��#W����&���ϕ/�ϟ�lӖ���J{<a(��+�O\XJ^�+�{Aܫ�|��
\ No newline at end of file diff --git a/bin/avlsdk3/Data/AVLXB000.IDX b/bin/avlsdk3/Data/AVLXB000.IDX Binary files differnew file mode 100644 index 0000000..15abe95 --- /dev/null +++ b/bin/avlsdk3/Data/AVLXB000.IDX diff --git a/bin/avlsdk3/Data/AVLXB001.DAT b/bin/avlsdk3/Data/AVLXB001.DAT Binary files differnew file mode 100644 index 0000000..80142f8 --- /dev/null +++ b/bin/avlsdk3/Data/AVLXB001.DAT diff --git a/bin/avlsdk3/Data/AVLXC001.ABP b/bin/avlsdk3/Data/AVLXC001.ABP Binary files differnew file mode 100644 index 0000000..8eb5a4c --- /dev/null +++ b/bin/avlsdk3/Data/AVLXC001.ABP diff --git a/bin/avlsdk3/Data/AVLXH001.ABP b/bin/avlsdk3/Data/AVLXH001.ABP Binary files differnew file mode 100644 index 0000000..974a941 --- /dev/null +++ b/bin/avlsdk3/Data/AVLXH001.ABP diff --git a/bin/avlsdk3/Data/AVLXM000.IDX b/bin/avlsdk3/Data/AVLXM000.IDX Binary files differnew file mode 100644 index 0000000..64534f2 --- /dev/null +++ b/bin/avlsdk3/Data/AVLXM000.IDX diff --git a/bin/avlsdk3/Data/AVLXM001.DAT b/bin/avlsdk3/Data/AVLXM001.DAT Binary files differnew file mode 100644 index 0000000..46ac4a1 --- /dev/null +++ b/bin/avlsdk3/Data/AVLXM001.DAT diff --git a/bin/avlsdk3/Data/AVLXT001.ABP b/bin/avlsdk3/Data/AVLXT001.ABP Binary files differnew file mode 100644 index 0000000..4eb8498 --- /dev/null +++ b/bin/avlsdk3/Data/AVLXT001.ABP diff --git a/bin/avlsdk3/Data/AVLXT001.DAT b/bin/avlsdk3/Data/AVLXT001.DAT Binary files differnew file mode 100644 index 0000000..5878da2 --- /dev/null +++ b/bin/avlsdk3/Data/AVLXT001.DAT diff --git a/bin/avlsdk3/License.alf b/bin/avlsdk3/License.alf new file mode 100644 index 0000000..0fb4238 --- /dev/null +++ b/bin/avlsdk3/License.alf @@ -0,0 +1,3 @@ +��H�������Kt$��V�Wթ ��T"���
�K��7K��܁�ߝ�Vn�n��:\�M< }�y+�Z���k�S1����T��_|x� {@���(�� 7�L��z�oW�P���X�W�^Q�и��]�#b�Eq��,y��H<��1�6���mՄ�=�n[4il��Dg�Z�X��B>^N�,F0)������Z� (�'�������3 +�ޗ�֊#;��0.�6���/��Y�HI�*�V!;ߐ,@wsg�\�����H�:Lξ�8�A�@*DM�A�;L���C��t��_Cp�PJԪ��ӷ��:�H�J�*q�P�{Ζ���A���`�5����l�xE�j\8��}��>E�M^�q6�v�[V�q��8�BD�}�фK���8AXW�}j:����o���(���pY�$ �#:[��3l��V=\֕�S#�i����j�Z/��J������k�+ +8�u�`O��5�4�Q�OI��D��Z�0�o��z� 3.0
\ No newline at end of file diff --git a/bin/avlsdk3/Module/ADInfoCl.so b/bin/avlsdk3/Module/ADInfoCl.so Binary files differnew file mode 100644 index 0000000..e86d9a8 --- /dev/null +++ b/bin/avlsdk3/Module/ADInfoCl.so diff --git a/bin/avlsdk3/Module/AIFilFmt.so b/bin/avlsdk3/Module/AIFilFmt.so Binary files differnew file mode 100644 index 0000000..bd5fe13 --- /dev/null +++ b/bin/avlsdk3/Module/AIFilFmt.so diff --git a/bin/avlsdk3/Module/AIPack.so b/bin/avlsdk3/Module/AIPack.so Binary files differnew file mode 100644 index 0000000..a00b2df --- /dev/null +++ b/bin/avlsdk3/Module/AIPack.so diff --git a/bin/avlsdk3/Module/AISfxArc.so b/bin/avlsdk3/Module/AISfxArc.so Binary files differnew file mode 100644 index 0000000..0c9daeb --- /dev/null +++ b/bin/avlsdk3/Module/AISfxArc.so diff --git a/bin/avlsdk3/Module/APSMail.so b/bin/avlsdk3/Module/APSMail.so Binary files differnew file mode 100644 index 0000000..6a7e11b --- /dev/null +++ b/bin/avlsdk3/Module/APSMail.so diff --git a/bin/avlsdk3/Module/APSPE.so b/bin/avlsdk3/Module/APSPE.so Binary files differnew file mode 100644 index 0000000..b16b141 --- /dev/null +++ b/bin/avlsdk3/Module/APSPE.so diff --git a/bin/avlsdk3/Module/APSScrpt.so b/bin/avlsdk3/Module/APSScrpt.so Binary files differnew file mode 100644 index 0000000..51e91b3 --- /dev/null +++ b/bin/avlsdk3/Module/APSScrpt.so diff --git a/bin/avlsdk3/Module/APUnArc.so b/bin/avlsdk3/Module/APUnArc.so Binary files differnew file mode 100644 index 0000000..0739e97 --- /dev/null +++ b/bin/avlsdk3/Module/APUnArc.so diff --git a/bin/avlsdk3/Module/APUnPack.so b/bin/avlsdk3/Module/APUnPack.so Binary files differnew file mode 100644 index 0000000..5e83087 --- /dev/null +++ b/bin/avlsdk3/Module/APUnPack.so diff --git a/bin/avlsdk3/Module/APUnSwf.so b/bin/avlsdk3/Module/APUnSwf.so Binary files differnew file mode 100644 index 0000000..8e7a306 --- /dev/null +++ b/bin/avlsdk3/Module/APUnSwf.so diff --git a/bin/avlsdk3/Module/APUnitEP.so b/bin/avlsdk3/Module/APUnitEP.so Binary files differnew file mode 100644 index 0000000..5a47c2c --- /dev/null +++ b/bin/avlsdk3/Module/APUnitEP.so diff --git a/bin/avlsdk3/Module/ASBOL.so b/bin/avlsdk3/Module/ASBOL.so Binary files differnew file mode 100644 index 0000000..8f279a6 --- /dev/null +++ b/bin/avlsdk3/Module/ASBOL.so diff --git a/bin/avlsdk3/Module/ASCommon.so b/bin/avlsdk3/Module/ASCommon.so Binary files differnew file mode 100644 index 0000000..0ad503f --- /dev/null +++ b/bin/avlsdk3/Module/ASCommon.so diff --git a/bin/avlsdk3/Module/ASDOH.so b/bin/avlsdk3/Module/ASDOH.so Binary files differnew file mode 100644 index 0000000..4d84c6a --- /dev/null +++ b/bin/avlsdk3/Module/ASDOH.so diff --git a/bin/avlsdk3/Module/ASDroid.so b/bin/avlsdk3/Module/ASDroid.so Binary files differnew file mode 100644 index 0000000..419c20b --- /dev/null +++ b/bin/avlsdk3/Module/ASDroid.so diff --git a/bin/avlsdk3/Module/ASELF.so b/bin/avlsdk3/Module/ASELF.so Binary files differnew file mode 100644 index 0000000..e61753e --- /dev/null +++ b/bin/avlsdk3/Module/ASELF.so diff --git a/bin/avlsdk3/Module/ASExplot.so b/bin/avlsdk3/Module/ASExplot.so Binary files differnew file mode 100644 index 0000000..305cc11 --- /dev/null +++ b/bin/avlsdk3/Module/ASExplot.so diff --git a/bin/avlsdk3/Module/ASKExplt.so b/bin/avlsdk3/Module/ASKExplt.so Binary files differnew file mode 100644 index 0000000..1be240a --- /dev/null +++ b/bin/avlsdk3/Module/ASKExplt.so diff --git a/bin/avlsdk3/Module/ASMacro.so b/bin/avlsdk3/Module/ASMacro.so Binary files differnew file mode 100644 index 0000000..8a8d3d2 --- /dev/null +++ b/bin/avlsdk3/Module/ASMacro.so diff --git a/bin/avlsdk3/Module/ASMalwB.so b/bin/avlsdk3/Module/ASMalwB.so Binary files differnew file mode 100644 index 0000000..119d48b --- /dev/null +++ b/bin/avlsdk3/Module/ASMalwB.so diff --git a/bin/avlsdk3/Module/ASMalwBA.so b/bin/avlsdk3/Module/ASMalwBA.so Binary files differnew file mode 100644 index 0000000..f2d258c --- /dev/null +++ b/bin/avlsdk3/Module/ASMalwBA.so diff --git a/bin/avlsdk3/Module/ASMalwFH.so b/bin/avlsdk3/Module/ASMalwFH.so Binary files differnew file mode 100644 index 0000000..05f0431 --- /dev/null +++ b/bin/avlsdk3/Module/ASMalwFH.so diff --git a/bin/avlsdk3/Module/ASMalwGH.so b/bin/avlsdk3/Module/ASMalwGH.so Binary files differnew file mode 100644 index 0000000..97d2e59 --- /dev/null +++ b/bin/avlsdk3/Module/ASMalwGH.so diff --git a/bin/avlsdk3/Module/ASMalwHS.so b/bin/avlsdk3/Module/ASMalwHS.so Binary files differnew file mode 100644 index 0000000..51d86cd --- /dev/null +++ b/bin/avlsdk3/Module/ASMalwHS.so diff --git a/bin/avlsdk3/Module/ASMalwNS.so b/bin/avlsdk3/Module/ASMalwNS.so Binary files differnew file mode 100644 index 0000000..404bbdb --- /dev/null +++ b/bin/avlsdk3/Module/ASMalwNS.so diff --git a/bin/avlsdk3/Module/ASMalwRG.so b/bin/avlsdk3/Module/ASMalwRG.so Binary files differnew file mode 100644 index 0000000..46455c3 --- /dev/null +++ b/bin/avlsdk3/Module/ASMalwRG.so diff --git a/bin/avlsdk3/Module/ASMalwS.so b/bin/avlsdk3/Module/ASMalwS.so Binary files differnew file mode 100644 index 0000000..203ff88 --- /dev/null +++ b/bin/avlsdk3/Module/ASMalwS.so diff --git a/bin/avlsdk3/Module/ASScript.so b/bin/avlsdk3/Module/ASScript.so Binary files differnew file mode 100644 index 0000000..8c24f5d --- /dev/null +++ b/bin/avlsdk3/Module/ASScript.so diff --git a/bin/avlsdk3/Module/ASSuf.so b/bin/avlsdk3/Module/ASSuf.so Binary files differnew file mode 100644 index 0000000..990bdfa --- /dev/null +++ b/bin/avlsdk3/Module/ASSuf.so diff --git a/bin/avlsdk3/Module/ASSwf.so b/bin/avlsdk3/Module/ASSwf.so Binary files differnew file mode 100644 index 0000000..bd6140f --- /dev/null +++ b/bin/avlsdk3/Module/ASSwf.so diff --git a/bin/avlsdk3/Module/ASVCS2S.so b/bin/avlsdk3/Module/ASVCS2S.so Binary files differnew file mode 100644 index 0000000..066ff4d --- /dev/null +++ b/bin/avlsdk3/Module/ASVCS2S.so diff --git a/bin/avlsdk3/Module/ASVirus.so b/bin/avlsdk3/Module/ASVirus.so Binary files differnew file mode 100644 index 0000000..bf63820 --- /dev/null +++ b/bin/avlsdk3/Module/ASVirus.so diff --git a/bin/avlsdk3/Module/AWSuf.so b/bin/avlsdk3/Module/AWSuf.so Binary files differnew file mode 100644 index 0000000..1b0b826 --- /dev/null +++ b/bin/avlsdk3/Module/AWSuf.so diff --git a/bin/avlsdk3/Module/AWUW.so b/bin/avlsdk3/Module/AWUW.so Binary files differnew file mode 100644 index 0000000..461d4e4 --- /dev/null +++ b/bin/avlsdk3/Module/AWUW.so diff --git a/bin/avlsdk3/NData/AVLA0000.NDB b/bin/avlsdk3/NData/AVLA0000.NDB Binary files differnew file mode 100644 index 0000000..4682564 --- /dev/null +++ b/bin/avlsdk3/NData/AVLA0000.NDB diff --git a/bin/avlsdk3/NData/AVLA0000.SDB b/bin/avlsdk3/NData/AVLA0000.SDB Binary files differnew file mode 100644 index 0000000..bf86b10 --- /dev/null +++ b/bin/avlsdk3/NData/AVLA0000.SDB diff --git a/bin/avlsdk3/NData/AVLAA000.NDB b/bin/avlsdk3/NData/AVLAA000.NDB Binary files differnew file mode 100644 index 0000000..426f030 --- /dev/null +++ b/bin/avlsdk3/NData/AVLAA000.NDB diff --git a/bin/avlsdk3/NData/AVLAA000.SDB b/bin/avlsdk3/NData/AVLAA000.SDB Binary files differnew file mode 100644 index 0000000..af5740b --- /dev/null +++ b/bin/avlsdk3/NData/AVLAA000.SDB diff --git a/bin/avlsdk3/NData/AVLB0000.NDB b/bin/avlsdk3/NData/AVLB0000.NDB Binary files differnew file mode 100644 index 0000000..e7de5c7 --- /dev/null +++ b/bin/avlsdk3/NData/AVLB0000.NDB diff --git a/bin/avlsdk3/NData/AVLB0000.SDB b/bin/avlsdk3/NData/AVLB0000.SDB Binary files differnew file mode 100644 index 0000000..61fcd3f --- /dev/null +++ b/bin/avlsdk3/NData/AVLB0000.SDB diff --git a/bin/avlsdk3/NData/AVLBF000.SDB b/bin/avlsdk3/NData/AVLBF000.SDB Binary files differnew file mode 100644 index 0000000..690d263 --- /dev/null +++ b/bin/avlsdk3/NData/AVLBF000.SDB diff --git a/bin/avlsdk3/NData/AVLC0000.NDB b/bin/avlsdk3/NData/AVLC0000.NDB Binary files differnew file mode 100644 index 0000000..34b7842 --- /dev/null +++ b/bin/avlsdk3/NData/AVLC0000.NDB diff --git a/bin/avlsdk3/NData/AVLC0000.SDB b/bin/avlsdk3/NData/AVLC0000.SDB Binary files differnew file mode 100644 index 0000000..36bb1c9 --- /dev/null +++ b/bin/avlsdk3/NData/AVLC0000.SDB diff --git a/bin/avlsdk3/NData/AVLD0000.NDB b/bin/avlsdk3/NData/AVLD0000.NDB Binary files differnew file mode 100644 index 0000000..e8fd0ae --- /dev/null +++ b/bin/avlsdk3/NData/AVLD0000.NDB diff --git a/bin/avlsdk3/NData/AVLD0000.SDB b/bin/avlsdk3/NData/AVLD0000.SDB Binary files differnew file mode 100644 index 0000000..c8a298c --- /dev/null +++ b/bin/avlsdk3/NData/AVLD0000.SDB diff --git a/bin/avlsdk3/NData/AVLEM000.NDB b/bin/avlsdk3/NData/AVLEM000.NDB Binary files differnew file mode 100644 index 0000000..4026e25 --- /dev/null +++ b/bin/avlsdk3/NData/AVLEM000.NDB diff --git a/bin/avlsdk3/NData/AVLEM000.SDB b/bin/avlsdk3/NData/AVLEM000.SDB Binary files differnew file mode 100644 index 0000000..bf86b10 --- /dev/null +++ b/bin/avlsdk3/NData/AVLEM000.SDB diff --git a/bin/avlsdk3/NData/AVLF0000.NDB b/bin/avlsdk3/NData/AVLF0000.NDB Binary files differnew file mode 100644 index 0000000..4c837f1 --- /dev/null +++ b/bin/avlsdk3/NData/AVLF0000.NDB diff --git a/bin/avlsdk3/NData/AVLF0000.SDB b/bin/avlsdk3/NData/AVLF0000.SDB Binary files differnew file mode 100644 index 0000000..50160e0 --- /dev/null +++ b/bin/avlsdk3/NData/AVLF0000.SDB diff --git a/bin/avlsdk3/NData/AVLF0001.SDB b/bin/avlsdk3/NData/AVLF0001.SDB Binary files differnew file mode 100644 index 0000000..48c6a52 --- /dev/null +++ b/bin/avlsdk3/NData/AVLF0001.SDB diff --git a/bin/avlsdk3/NData/AVLFM000.NDB b/bin/avlsdk3/NData/AVLFM000.NDB Binary files differnew file mode 100644 index 0000000..45fce87 --- /dev/null +++ b/bin/avlsdk3/NData/AVLFM000.NDB diff --git a/bin/avlsdk3/NData/AVLFM000.SDB b/bin/avlsdk3/NData/AVLFM000.SDB Binary files differnew file mode 100644 index 0000000..548bb06 --- /dev/null +++ b/bin/avlsdk3/NData/AVLFM000.SDB diff --git a/bin/avlsdk3/NData/AVLH0000.SDB b/bin/avlsdk3/NData/AVLH0000.SDB Binary files differnew file mode 100644 index 0000000..36bb1c9 --- /dev/null +++ b/bin/avlsdk3/NData/AVLH0000.SDB diff --git a/bin/avlsdk3/NData/AVLIM000.NDB b/bin/avlsdk3/NData/AVLIM000.NDB Binary files differnew file mode 100644 index 0000000..dd81d22 --- /dev/null +++ b/bin/avlsdk3/NData/AVLIM000.NDB diff --git a/bin/avlsdk3/NData/AVLIM000.SDB b/bin/avlsdk3/NData/AVLIM000.SDB Binary files differnew file mode 100644 index 0000000..ac058ef --- /dev/null +++ b/bin/avlsdk3/NData/AVLIM000.SDB diff --git a/bin/avlsdk3/NData/AVLK0000.NDB b/bin/avlsdk3/NData/AVLK0000.NDB Binary files differnew file mode 100644 index 0000000..9490f74 --- /dev/null +++ b/bin/avlsdk3/NData/AVLK0000.NDB diff --git a/bin/avlsdk3/NData/AVLK0000.SDB b/bin/avlsdk3/NData/AVLK0000.SDB Binary files differnew file mode 100644 index 0000000..72118a3 --- /dev/null +++ b/bin/avlsdk3/NData/AVLK0000.SDB diff --git a/bin/avlsdk3/NData/AVLLB000.NDB b/bin/avlsdk3/NData/AVLLB000.NDB Binary files differnew file mode 100644 index 0000000..dfbf5b7 --- /dev/null +++ b/bin/avlsdk3/NData/AVLLB000.NDB diff --git a/bin/avlsdk3/NData/AVLLB000.SDB b/bin/avlsdk3/NData/AVLLB000.SDB Binary files differnew file mode 100644 index 0000000..ac60574 --- /dev/null +++ b/bin/avlsdk3/NData/AVLLB000.SDB diff --git a/bin/avlsdk3/NData/AVLMS000.NDB b/bin/avlsdk3/NData/AVLMS000.NDB Binary files differnew file mode 100644 index 0000000..212f78f --- /dev/null +++ b/bin/avlsdk3/NData/AVLMS000.NDB diff --git a/bin/avlsdk3/NData/AVLMS000.SDB b/bin/avlsdk3/NData/AVLMS000.SDB Binary files differnew file mode 100644 index 0000000..a42efab --- /dev/null +++ b/bin/avlsdk3/NData/AVLMS000.SDB diff --git a/bin/avlsdk3/NData/AVLO0000.NDB b/bin/avlsdk3/NData/AVLO0000.NDB Binary files differnew file mode 100644 index 0000000..e5ee889 --- /dev/null +++ b/bin/avlsdk3/NData/AVLO0000.NDB diff --git a/bin/avlsdk3/NData/AVLO0000.SDB b/bin/avlsdk3/NData/AVLO0000.SDB Binary files differnew file mode 100644 index 0000000..400ee5a --- /dev/null +++ b/bin/avlsdk3/NData/AVLO0000.SDB diff --git a/bin/avlsdk3/NData/AVLO0001.SDB b/bin/avlsdk3/NData/AVLO0001.SDB Binary files differnew file mode 100644 index 0000000..6627146 --- /dev/null +++ b/bin/avlsdk3/NData/AVLO0001.SDB diff --git a/bin/avlsdk3/NData/AVLRD000.NDB b/bin/avlsdk3/NData/AVLRD000.NDB Binary files differnew file mode 100644 index 0000000..01c7143 --- /dev/null +++ b/bin/avlsdk3/NData/AVLRD000.NDB diff --git a/bin/avlsdk3/NData/AVLRD000.SDB b/bin/avlsdk3/NData/AVLRD000.SDB Binary files differnew file mode 100644 index 0000000..321383c --- /dev/null +++ b/bin/avlsdk3/NData/AVLRD000.SDB diff --git a/bin/avlsdk3/NData/AVLRM000.NDB b/bin/avlsdk3/NData/AVLRM000.NDB Binary files differnew file mode 100644 index 0000000..d1f8fa4 --- /dev/null +++ b/bin/avlsdk3/NData/AVLRM000.NDB diff --git a/bin/avlsdk3/NData/AVLRM000.SDB b/bin/avlsdk3/NData/AVLRM000.SDB Binary files differnew file mode 100644 index 0000000..83980c2 --- /dev/null +++ b/bin/avlsdk3/NData/AVLRM000.SDB diff --git a/bin/avlsdk3/NData/AVLSB000.NDB b/bin/avlsdk3/NData/AVLSB000.NDB Binary files differnew file mode 100644 index 0000000..c09e577 --- /dev/null +++ b/bin/avlsdk3/NData/AVLSB000.NDB diff --git a/bin/avlsdk3/NData/AVLSB000.SDB b/bin/avlsdk3/NData/AVLSB000.SDB Binary files differnew file mode 100644 index 0000000..5072173 --- /dev/null +++ b/bin/avlsdk3/NData/AVLSB000.SDB diff --git a/bin/avlsdk3/NData/AVLSB001.SDB b/bin/avlsdk3/NData/AVLSB001.SDB Binary files differnew file mode 100644 index 0000000..47d48b5 --- /dev/null +++ b/bin/avlsdk3/NData/AVLSB001.SDB diff --git a/bin/avlsdk3/NData/AVLST000.NDB b/bin/avlsdk3/NData/AVLST000.NDB Binary files differnew file mode 100644 index 0000000..cdaa8fa --- /dev/null +++ b/bin/avlsdk3/NData/AVLST000.NDB diff --git a/bin/avlsdk3/NData/AVLST000.SDB b/bin/avlsdk3/NData/AVLST000.SDB Binary files differnew file mode 100644 index 0000000..cc62c79 --- /dev/null +++ b/bin/avlsdk3/NData/AVLST000.SDB diff --git a/bin/avlsdk3/NData/AVLV0000.IDX b/bin/avlsdk3/NData/AVLV0000.IDX Binary files differnew file mode 100644 index 0000000..b855842 --- /dev/null +++ b/bin/avlsdk3/NData/AVLV0000.IDX diff --git a/bin/avlsdk3/NData/AVLV0000.NDB b/bin/avlsdk3/NData/AVLV0000.NDB Binary files differnew file mode 100644 index 0000000..8572f60 --- /dev/null +++ b/bin/avlsdk3/NData/AVLV0000.NDB diff --git a/bin/avlsdk3/NData/AVLV0000.SDB b/bin/avlsdk3/NData/AVLV0000.SDB Binary files differnew file mode 100644 index 0000000..373a09e --- /dev/null +++ b/bin/avlsdk3/NData/AVLV0000.SDB diff --git a/bin/avlsdk3/NData/AVLWD000.NDB b/bin/avlsdk3/NData/AVLWD000.NDB Binary files differnew file mode 100644 index 0000000..505687b --- /dev/null +++ b/bin/avlsdk3/NData/AVLWD000.NDB diff --git a/bin/avlsdk3/NData/AVLWD000.SDB b/bin/avlsdk3/NData/AVLWD000.SDB Binary files differnew file mode 100644 index 0000000..6f05566 --- /dev/null +++ b/bin/avlsdk3/NData/AVLWD000.SDB diff --git a/bin/avlsdk3/NData/AVLWG000.NDB b/bin/avlsdk3/NData/AVLWG000.NDB Binary files differnew file mode 100644 index 0000000..db5eeef --- /dev/null +++ b/bin/avlsdk3/NData/AVLWG000.NDB diff --git a/bin/avlsdk3/NData/AVLWG000.SDB b/bin/avlsdk3/NData/AVLWG000.SDB Binary files differnew file mode 100644 index 0000000..6486839 --- /dev/null +++ b/bin/avlsdk3/NData/AVLWG000.SDB diff --git a/bin/avlsdk3/NData/AVLXB000.NDB b/bin/avlsdk3/NData/AVLXB000.NDB Binary files differnew file mode 100644 index 0000000..893e699 --- /dev/null +++ b/bin/avlsdk3/NData/AVLXB000.NDB diff --git a/bin/avlsdk3/NData/AVLXB000.SDB b/bin/avlsdk3/NData/AVLXB000.SDB Binary files differnew file mode 100644 index 0000000..61a60c2 --- /dev/null +++ b/bin/avlsdk3/NData/AVLXB000.SDB diff --git a/bin/avlsdk3/aid2name.so b/bin/avlsdk3/aid2name.so Binary files differnew file mode 100644 index 0000000..df5e77c --- /dev/null +++ b/bin/avlsdk3/aid2name.so diff --git a/bin/conf/objectscan.conf b/bin/conf/objectscan.conf new file mode 100644 index 0000000..7e64ea2 --- /dev/null +++ b/bin/conf/objectscan.conf @@ -0,0 +1,64 @@ +[OBJSCAN] +MAX_QUEUE_ELEMENTS=100000 +#The maximum size of each object to scan. +ANALYZE_MAX_SIZE=1048576 +ANALYZE_THREAD_NUM=1 +DELAY_ANALYZE_TIME_S=20 + +KAFKA_BROKSER_IPLIST=192.168.10.12; +KAFKA_BROKSER_PORT=9092 + +LOG_FSSTAT_INTERVAL=60 +LOG_FSSTAT_DST_IP=127.0.0.1 +LOG_FSSTAT_DST_PORT=8125 +LOG_FSSTAT_TRIG=1 + +[TANGO_CACHE] +#Addresses of minio. Format is defined by WiredLB. +minio_ip_list=192.168.10.27; +minio_listen_port=9000 +#For Non-Struct logs, we will use Nginx as a proxy to access each object. Set Nginx's port. +minio_proxy_port=9100 +#Maximum number of connections opened by per host. +#max_connection_per_host=1 +#Maximum number of requests in a pipeline. +#max_cnnt_pipeline_num=20 +#Maximum parellel sessions(http and redis) is allowed to open. +#max_curl_session_num=20 +#Maximum time the request is allowed to take(seconds). +#max_curl_transfer_timeout_s=0 + +#Bucket name in minio. +cache_bucket_name=openbucket +cache_bucket_num=32 +#Maximum size of memory used by tango_cache_client. Upload will fail if the current size of memory used exceeds this value. +max_used_memory_size_mb=5120 +cache_upload_losf_size=4194304 +#When use LOSF mode, objects will be uploaded even if its total size doesnt reach $cache_upload_losf_size after timeouts. +#cache_upload_losf_timeout_s=10 +#Default TTL of objects, i.e. the time after which the object will expire(minumun 60s, i.e. 1 minute). +cache_default_ttl_second=36000 +#Whether to hash the object key before cache actions. GET/PUT may be faster if you open it. +cache_object_key_hash_switch=0 + +#Store way: 0-MINIO; 1-LOSF, META in REDIS, object in minio; 2-META and small object in Redis, large object in minio; +cache_store_object_way=1 +#If $cache_store_object_way is 2 and the size of a object is not bigger than this value, object will be stored in redis. +redis_cache_object_size=512000 +#max_redis_session_num=800 +#If $cache_store_object_way is not 0, we will use redis to store meta and object. +redis_cluster_ip_list=192.168.10.27; +redis_cluster_port_range=7101-7106; +#Configs of WiredLB for Minios load balancer. +#wiredlb_override=1 +#wiredlb_topic= +#wiredlb_datacenter= +wiredlb_health_port=52102 +#wiredlb_group= + +log_fsstat_appname=TANGO_CACHE +log_fsstat_filepath=./log/field_stat.log +log_fsstat_interval=10 +log_fsstat_trig=1 +log_fsstat_dst_ip=127.0.0.1 +log_fsstat_dst_port=8125 diff --git a/bin/log/field_stat.log b/bin/log/field_stat.log new file mode 100644 index 0000000..c8414b2 --- /dev/null +++ b/bin/log/field_stat.log @@ -0,0 +1,16 @@ +============================================================Mon Jun 3 18:09:20 2019============================================================ +MEM_USED: 0 SESSION_HTTP: 0 SESSION_REDIS: 0 +________________________________________________________________________________________________________________________________________________ + GET_RECV GET_S_TOTAL GET_S_HTTP GET_S_REDIS GET_MISS GET_E_TOTAL GET_E_HTTP GET_E_REDIS +sum 0 0 0 0 0 0 0 0 +speed/s 0 0 0 0 0 0 0 0 + PUT_RECV PUT_S_TOTAL PUT_S_HTTP PUT_S_REDIS PUT_CANCEL PUT_E_TOTAL PUT_E_HTTP PUT_E_REDIS +sum 0 0 0 0 0 0 0 0 +speed/s 0 0 0 0 0 0 0 0 + PUT_LOSF DEL_RECV DEL_SUCC DEL_ERROR TOTAL_DROP +sum 0 0 0 0 0 +speed/s 0 0 0 0 0 +________________________________________________________________________________________________________________________________________________ +histogram 50.00% 80.00% 90.00% 95.00% 99.00% MAX MIN AVG STDDEV CNT +length(bytes) 0 0 0 0 0 0 0 0.00 0.00 0 +________________________________________________________________________________________________________________________________________________ diff --git a/bin/log/log_statistic/statistic.log b/bin/log/log_statistic/statistic.log new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/bin/log/log_statistic/statistic.log diff --git a/bin/log/objscan_fsstat.log b/bin/log/objscan_fsstat.log new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/bin/log/objscan_fsstat.log diff --git a/bin/log/runtime_log/runtime.log b/bin/log/runtime_log/runtime.log new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/bin/log/runtime_log/runtime.log diff --git a/bin/object_scanner b/bin/object_scanner Binary files differnew file mode 100644 index 0000000..54f834c --- /dev/null +++ b/bin/object_scanner diff --git a/bin/object_scanner_dmn.sh b/bin/object_scanner_dmn.sh new file mode 100644 index 0000000..bab28ed --- /dev/null +++ b/bin/object_scanner_dmn.sh @@ -0,0 +1,16 @@ +#!/bin/bash +while [ 1 ]; +do + count=`ls -l core.* |wc -l` + if [ $count -lt 3 ] + then + ulimit -c unlimited + else + ulimit -c 0 + fi + + ./object_scanner >> /dev/null + echo program crashed, restart at `date +"%w %Y/%m/%d, %H:%M:%S"` >> RESTART.log + sleep 30 +done + diff --git a/bin/object_scanner_start.sh b/bin/object_scanner_start.sh new file mode 100644 index 0000000..6711953 --- /dev/null +++ b/bin/object_scanner_start.sh @@ -0,0 +1,3 @@ +#!/bin/bash +killall object_scanner_dmn.sh object_scanner +./object_scanner_dmn.sh &>/dev/null & diff --git a/bin/object_scanner_stop.sh b/bin/object_scanner_stop.sh new file mode 100644 index 0000000..3332ca3 --- /dev/null +++ b/bin/object_scanner_stop.sh @@ -0,0 +1,2 @@ +#!/bin/bash +killall object_scanner_dmn.sh object_scanner diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..5ef1901 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,33 @@ +CCC=g++ +CC=gcc + +INC_PATH=-I./include +CFLAGS= -g $(INC_PATH) +#CFLAGS=-Wall -g $(INC_PATH) +LDFLAGS = +LIBS = ./libs/libtango_cache_client.a ./libs/libcjson.a ./libs/libcrypto.a ./libs/libcurl.a ./libs/libevent.a ./libs/libhiredis_vip.a ./libs/libssl.a ./libs/libxml2.a +LIBS += -lMESA_handle_logger -lMESA_htable -lMESA_prof_load -lMESA_field_stat2 -lpthread -lwiredcfg -lWiredLB -lrdkafka +LIBS += -laid2name -lAVLSDK + +OBJS = objectscanner_analyze.o objectscanner_kafka.o objectscanner_main.o +DEPS = $(OBJS:.o=.d) + +TARGET_EXE=object_scanner + +ALL:$(TARGET_EXE) + +$(TARGET_EXE):$(OBJS) + $(CCC) $(LDFLAGS) $^ -o $@ $(LIBS) + cp $@ ../bin/ + +.c.o: + $(CCC) $(CFLAGS) -c $< + +.cpp.o: + $(CCC) $(CFLAGS) -c $< + +-include $(DEPS) + +clean: + rm -rf $(OBJS) $(DEPS) $(TARGET_EXE) + diff --git a/src/include/MESA/MESA_handle_logger.h b/src/include/MESA/MESA_handle_logger.h new file mode 100644 index 0000000..c615b53 --- /dev/null +++ b/src/include/MESA/MESA_handle_logger.h @@ -0,0 +1,68 @@ +#ifndef MESA_HANDLE__LOGGER_H +#define MESA_HANDLE__LOGGER_H + +/* + * runtime_log with handle, + * based on runtime_log. + * yang wei + * create time:2014-03-24 + * version:20140324 + */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define RLOG_LV_DEBUG 10 +#define RLOG_LV_INFO 20 +#define RLOG_LV_FATAL 30 + + +#define MESA_HANDLE_RUNTIME_LOG(handle, lv, mod, fmt, args...) \ + MESA_handle_runtime_log((handle), (lv), (mod), "file %s, line %d, " fmt, \ + __FILE__, __LINE__, ##args) + +/* + * name: MESA_create_runtime_log_handle + * functionality: get runtime_log handle; + * params: + * file_path: path of log file, like "./log/runtime_log"; + * level: level of log; + * returns: + * not NULL, if succeeded; + * NULL, if file is not absolute path, or failed to create log file; + */ +void *MESA_create_runtime_log_handle(const char *file_path, int level); + +/* + * name: MESA_handle_runtime_log + * functionality: appends log message to runtime log file; + * params: + * handle:handle of runtime log, which is created by MESA_create_runtime_log_handle; + * level: log level, messages with level value smaller the global var + * "runtime_log_level" are ignored; + * module: name of loggin module; + * fmt: format string; + * returns: + * none; + */ +void MESA_handle_runtime_log(void *handle, int level, const char *module, const char *fmt, ...); + +/* + * name: MESA_destroy_runtime_log_handle + * functionality: release runtime log handle memory. + * params: + * handle: runtime log handle which is going to be released; + * returns: + * none; + */ +void MESA_destroy_runtime_log_handle(void *handle); + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/src/include/MESA/MESA_htable.h b/src/include/MESA/MESA_htable.h new file mode 100644 index 0000000..54343ee --- /dev/null +++ b/src/include/MESA/MESA_htable.h @@ -0,0 +1,378 @@ +#ifndef __MESA_HTABLE_H_ +#define __MESA_HTABLE_H_ +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <pthread.h> + +/* + * general purpose hash table implementation. + * + * xiang hong + * 2002-07-28 + *History: + * 2012-03-23 zhengchao add thread safe option and link expire feature; + * 2014-01-27 lijia add reentrant feature. + */ + +#define MESA_HASH_DEBUG (0) + +#define COMPLEX_KEY_SWITCH (1) + +#define ELIMINATE_TYPE_NUM (1) +#define ELIMINATE_TYPE_TIME (2) +#define ELIMINATE_TYPE_MANUAL (3) /* delete oldest item by manual */ + +typedef void * MESA_htable_handle; + + +#define HASH_MALLOC(_n_) malloc(_n_) +#define HASH_FREE(_p_) free(_p_) + + +#ifndef uchar +#define uchar unsigned char +#endif +#ifndef uint +#define uint unsigned int +#endif + +/* eliminate algorithm */ +#define HASH_ELIMINATE_ALGO_FIFO (0) /* by default */ +#define HASH_ELIMINATE_ALGO_LRU (1) + +/* + * hash key compare function prototype, see hash_key_comp(). + * return value: + * 0:key1 and key2 are equal; + * other:key1 and key2 not equal. + */ +typedef int key_comp_fun_t(const uchar * key1, uint size1, const uchar * key2, uint size2); + +/* + * hash key->index computing function prototype, see hash_key2index(). + */ +typedef uint key2index_fun_t(const MESA_htable_handle table, const uchar * key, uint size); + +typedef void MESA_htable_data_free_cbfun_t(void *data); + +typedef int MESA_htable_expire_notify_cbfun_t(void *data, int eliminate_type); + +typedef uchar* MESA_htable_complex_key_dup_cbfun_t(const uchar *key, uint key_size); + +typedef void MESA_htable_complex_key_free_cbfun_t(uchar *key, uint key_size); + +typedef long hash_cb_fun_t(void *data, const uchar *key, uint size, void *user_arg); + +/* + * thread_safe: 0:create hash table without thread safe features; + * positive:the bigger number has more performance, less collide, but less timeout accuracy. + * max number is 1024. + * recursive: 0:can't recursive call MESA_htable_xxx series function + * 1:can recursive call MESA_htable_xxx series function. + * hash_slot_size: how big do you want the table to be, must be 2^N; + * max_elem_num: the maximum elements of the HASH-table,0 means infinite; + * key_comp: hash key compare function, use default function if NULL; + * suggest implement by yourself. + * key2index: hash key->index computing function, use default function if NULL; + * suggest use MESA_htable built-in function. + * data_free: release resources function; + * data_expire_with_condition: + * if expire_time > 0 and data_expire_with_condition != NULL, + * then call this function when an element expired, and give the reason by the 'type' + * if expire_time > 0 and data_expire_with_condition is NULL, + * eliminate the item immediately; + * args: + * data: pointer to attached data; + * type: item eliminate reason, ELIMINATE_TYPE_NUM or ELIMINATE_TYPE_TIME; + * return value of 'data_expire_with_condition': + * 1: the item can be eliminated; + * 0: the item can't be eliminated, renew the item. + * eliminate_type: the algorithm of elimanate a expired element, 0:FIFO; 1:LRU. + * expire_time: the element expire time in second, 0 means infinite. + */ +typedef struct{ + unsigned int thread_safe; + int recursive; + unsigned int hash_slot_size; + unsigned int max_elem_num; + int eliminate_type; + int expire_time; + key_comp_fun_t * key_comp; + key2index_fun_t * key2index; + void (* data_free)(void *data); + int (*data_expire_with_condition)(void *data, int eliminate_type); +#if COMPLEX_KEY_SWITCH + uchar* (*complex_key_dup)(const uchar *key, uint key_size); + void (* complex_key_free)(uchar *key, uint key_size); +#endif +}MESA_htable_create_args_t; + + +/* All of the following functions return value */ +typedef enum{ + MESA_HTABLE_RET_OK = 0, /* success */ + MESA_HTABLE_RET_COMMON_ERR = -1, /* general��undefined errors */ + MESA_HTABLE_RET_ARG_ERR = -2, /* invalid args */ + MESA_HTABLE_RET_NUM_FULL = -3, /* htable number full */ + MESA_HTABLE_RET_QEMPTY = -4, /* htable empty */ + MESA_HTABLE_RET_DUP_ITEM = -5, /* duplicate item */ + MESA_HTABLE_RET_NOT_FOUND = -6, /* not found item */ + MESA_HTABLE_RET_LEN_ERR = -7, /* length error */ + MESA_HTABLE_RET_CANT_GET_LOCK = -8, /* can't get lock in non-block mode */ + MESA_HTABLE_RET_GET_LOCK_TMOUT = -9, /* get lock timeout */ +}MESA_htable_errno_t; + +/* + * You should never use this API to create a hash table, use MESA_htable_born() instead. + * name: MESA_htable_create + * functionality: allocats memory for hash slots, and initialize hash structure; + * param: + * args: argments set; + * args_len: length of argment set; + * returns: + * NULL : error; + * Non-NULL : success; + */ +MESA_htable_handle MESA_htable_create(const MESA_htable_create_args_t *args, int args_struct_len); + +/* + * get total number of HASH element. +*/ +unsigned int MESA_htable_get_elem_num(const MESA_htable_handle table); + +/* + * name: MESA_htable_destroy + * functionality: cleans up hash structure, frees memory occupied; + * param: + * table: who is the victim; + * func: callback function to clean up data attached to hash items, has higher priority level than MESA_htable_data_free_cbfun_t in initialization. + + * returns: + * always returns 0; + */ +int MESA_htable_destroy(MESA_htable_handle table, void (* func)(void *)); + +/* + * name: MESA_htable_add + * functionality: adds item to table, call hash_expire() if elem_count gets + * bigger than threshold_hi, and adjust threshold; + * param: + * table: to which table do you want to add; + * key: what is the label; + * size: how long is the label; + * data: what data do you want to attach; + * returns: + * 0: success. + * <0: error, refer to MESA_htable_errno_t. + */ +int MESA_htable_add(MESA_htable_handle table, const uchar * key, uint size, const void *data); +#if 0 +/* + * name: hash_add_with_expire + * functionality: adds item to table, than call hash_expire() on its list + * param: + * table: to which table do you want to add; + * key: what is the label; + * size: how long is the label; + * data: what data do you want to attach; + * returns: + * >0 success,return hash elems' linklist size + * -1, duplicates found and can't add this one; + * -2, memory failure; + */ +int MESA_hash_add_with_expire_v3(MESA_htable_inner_t * table, uchar * key, uint size, void * data); + +#endif + + +/* + * name: MESA_htable_del + * functionality: deletes item from table. + * param: + * table: from which table do you want to delete; + * key : what is the label; + * size : how long is the label; + * func : callback function to clean up data attached to hash items, + if this pointer is NULL will call "data_free" in MESA_hash_create(), + * returns: + * 0 : success; + * <0: error, refer to MESA_htable_errno_t. + */ +int MESA_htable_del(MESA_htable_handle table, const uchar * key, uint size, + void (* func)(void *)); + +/* + * name: MESA_htable_del_oldest_manual + * functionality: deletes oldest item from table. + * param: + * table: from which table do you want to delete; + * func : callback function to clean up data attached to hash items, + if this pointer is NULL will call "data_free" in MESA_hash_create(), + * batch_num: delete oldest items. + * returns: + * 0, do nothing ; + * >0, delete items; + */ +int MESA_htable_del_oldest_manual(MESA_htable_handle table, void (* func)(void *), int batch_num); + +/* + * name: MESA_htable_search + * functionality: selects item from table; + * param: + * table: from which table do you want to select; + * key : what is the label; + * size : how long is the label; + * + * return: + * not NULL :pointer to attached data; + * NULL :not found(thus be careful if you are attaching NULL data on purpose). + */ +void *MESA_htable_search(const MESA_htable_handle table, const uchar * key, uint size); + +/* + * name: MESA_htable_search_cb + * functionality: selects item from table, and then call 'cb', reentrant; + * in param: + * table: from which table do you want to select; + * key : what is the label; + * size : how long is the label; + * cb : call this function when found the attached data; + * arg : the argument of "cb" function. + * out param: + * cb_ret: the return value of the function "cb". + * return: + * not NULL :pointer to attached data; + * NULL :not found(thus be careful if you are attaching NULL data on purpose). + */ +void *MESA_htable_search_cb(const MESA_htable_handle table, const uchar * key, uint size, + hash_cb_fun_t *cb, void *arg, long *cb_ret); + +/* + * name: MESA_htable_iterate + * functionality: iterates each hash item; + * params: + * table: what table is to be iterated; + * func: what do you want to do to each attached data item; + * returns: + * 0: iterates all items; + * -1: error; + */ +int MESA_htable_iterate(MESA_htable_handle table, + void (* func)(const uchar * key, uint size, void * data, void *user), void * user); + + +/* + * name: MESA_htable_iterate_bytime + * functionality: iterates each hash item by your demand; + * note: + * if 'thread_safe' more than one, this function is not correct. + * params: + * table: what table is to be iterated; + * iterate_type: 1: newest item first; 2: oldest item first; + * iterate_cb: what do you want to do to each attached data item; + * return value of iterate_cb: + * refer to ITERATE_CB_RET_xxx; + * returns: + * 0: iterates all items; + * -1: uncomplete break. + * -2: error; + */ +#define ITERATE_CB_RET_CONTINUE_FLAG (0) /* default, like MESA_htable_iterate() */ +#define ITERATE_CB_RET_BREAK_FLAG (1<<1) /* break iterate, return from MESA_htable_iterate_bytime() immediately */ +#define ITERATE_CB_RET_DEL_FLAG (1<<2) /* del this item, like but faster than call MESA_htable_del() */ +#define ITERATE_CB_RET_REVERSE_FLAG (1<<3) /* if the item is newest item, it will become the oldest item, and vice versa */ +#define ITERATE_CB_RET_REMOVE_BUT_NOT_FREE (1<<4) /* only remove the item from Hash table, but don't free the attached data, be careful */ + +#define ITERATE_TYPE_NEWEST_FIRST (1) +#define ITERATE_TYPE_OLDEST_FIRST (2) +int MESA_htable_iterate_bytime(MESA_htable_handle table, int iterate_type, + int (*iterate_cb)(const uchar * key, uint size, void * data, void *user), void * user); + +/* + args: + print_switch: + 0: disable print message; + 1: enable print message; +*/ +void MESA_htable_print_crtl(MESA_htable_handle table, int print_switch); + + +/* + Create a htable handle and Alloc memory, and set default option, + but can't running before call MESA_htable_mature(). + + return value: + not NULL: success. + NULL : error. +*/ +MESA_htable_handle MESA_htable_born(void); + +/* + MESA_htable option definition. +*/ +enum MESA_htable_opt{ + MHO_THREAD_SAFE = 0, /* must be int, 1:create hash table with thread safe features, default is 0 */ + MHO_MUTEX_NUM, /* must be int, valid only if MHO_THREAD_SAFE is not zero, max value is 1024, defalut is 1. the bigger number has more performance and less mutex collide, but less timeout accuracy */ + MHO_HASH_SLOT_SIZE, /* must be unsigned int, default is 1048576. */ + MHO_HASH_MAX_ELEMENT_NUM, /* must be unsigned int, defalut is 0, means infinite */ + MHO_EXPIRE_TIME, /* must be int, defalut is 0, means infinite */ + MHO_ELIMIMINATE_TYPE, /* must be int, valid only if MHO_EXPIRE_TIME is not zero. HASH_ELIMINATE_ALGO_FIFO or HASH_ELIMINATE_ALGO_LRU, defalut HASH_ELIMINATE_ALGO_FIFO */ + MHO_CBFUN_KEY_COMPARE, /* must be key_comp_fun_t, hash key compare function, use default function if NULL */ + MHO_CBFUN_KEY_TO_INDEX, /* must be key2index_fun_t, hash key->index computing function, use default function if NULL */ + MHO_CBFUN_DATA_FREE, /* must be MESA_htable_data_free_cbfun_t, release resources function */ + /* data_expire_notify, must be MESA_htable_expire_notify_cbfun_t, + * if expire_time > 0 and data_expire_notify != NULL, + * then call this function when an element expired, and give the reason by the 'type' + * if expire_time > 0 and data_expire_notify is NULL, + * eliminate the item immediately; + * args: + * data: pointer to attached data; + * type: item eliminate reason, ELIMINATE_TYPE_NUM or ELIMINATE_TYPE_TIME; + * return value of 'data_expire_with_condition': + * 1: the item can be eliminated; + * 0: the item can't be eliminated, renew the item. + */ + MHO_CBFUN_DATA_EXPIRE_NOTIFY, + MHO_CBFUN_COMPLEX_KEY_DUP, /* must be MESA_htable_complex_key_dup_cbfun_t, if key store in a complex struct, caller must be implement this duplicate function. */ + MHO_CBFUN_COMPLEX_KEY_FREE, /* must be MESA_htable_complex_key_free_cbfun_t, if key store in a complex struct, caller must be implement this duplicate function. */ + MHO_AUTO_UPDATE_TIME, /* must be int, create a background thread used to update current_time instead of time(NULL). 1:enable; 0:disable; default value is 0; */ + MHO_SCREEN_PRINT_CTRL, /* must be int, 1:enable screen print; 0:disable screen print; default is 1. */ + __MHO_MAX_VAL, /* caller can't use this definition, it's value maybe changed in next version!! */ +}; + + +/* + to set features of specified MESA_htable handle. + opt_type: option type, refer to enum MESA_htable_opt; + opt_val : option value, depend on opt type; + opt_len : opt_val size, depend on opt type; + + return value: + 0 :success; + <0:error; +*/ +int MESA_htable_set_opt(MESA_htable_handle table, enum MESA_htable_opt opt_type, void *opt_val, int opt_len); + +/* + Construct htable and ready to running. + + return value: + 0 : success; + <0: error. +*/ +int MESA_htable_mature(MESA_htable_handle table); + + +#ifdef __cplusplus +} +#endif + +#endif /* _LIB_HASH_H_INCLUDED_ */ + + diff --git a/src/include/MESA/MESA_list_queue.h b/src/include/MESA/MESA_list_queue.h new file mode 100644 index 0000000..08ce32b --- /dev/null +++ b/src/include/MESA/MESA_list_queue.h @@ -0,0 +1,115 @@ +#ifndef _MESA_LIST_QUEUE_H_ +#define _MESA_LIST_QUEUE_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* + MESA_list �����棬 + 1-�����̰߳�ȫ����; + 2-�����ڲ��ṹ, ����ȫ���ӿڸ����; + 3-�������������й����ڵ�ṹ��ʹ�ø�����; +*/ + +#define MESA_LIST_QUEUE_VERSION_MACRO (20160308) +extern const unsigned int MESA_LIST_QUEUE_VERSION_INT; + +#define MESA_LIST_OP_PLACE_HEAD (0x1) +#define MESA_LIST_OP_PLACE_TAIL (0x2) + +#define MESA_list_GET (0x1) +#define MESA_list_JOIN (0x2) + +#define MESA_list_BOLCK (0x4) +#define MESA_list_NONBOLCK (0x8) + +#define MESA_list_JOIN_BLOCK (MESA_list_JOIN|MESA_list_BOLCK) +#define MESA_list_JOIN_NONBLOCK (MESA_list_JOIN|MESA_list_NONBOLCK) +#define MESA_list_GET_BLOCK (MESA_list_GET|MESA_list_BOLCK) +#define MESA_list_GET_NONBLOCK (MESA_list_GET|MESA_list_NONBOLCK) + +typedef void * MESA_lqueue_head; +typedef int (* MESA_lqueue_cb_t)(void *data, long data_len, void *arg); + +/* All of the following functions return value */ +typedef enum{ + MESA_QUEUE_RET_OK = 0, /* success */ + MESA_QUEUE_RET_COMMON_ERR = -1, /* general��undefined errors */ + MESA_QUEUE_RET_ARG_ERR = -2, /* invalid args */ + MESA_QUEUE_RET_NUM_FULL = -3, /* queue number full */ + MESA_QUEUE_RET_MEM_FULL = -4, /* queue memory full */ + MESA_QUEUE_RET_QEMPTY = -5, /* queue empty */ + MESA_QUEUE_RET_LEN_ERR = -6, /* length error */ + MESA_QUEUE_RET_CANT_GET_LOCK = -7, /* can't get lock in non-block mode */ + MESA_QUEUE_RET_GET_LOCK_TMOUT = -8, /* get lock timeout */ +}MESA_queue_errno_t; + +/* + args description: + [IN] + thread_safe : 1:create thread safe queue; 0:without thread safe insurance. + max_item_num: maximum queue items of the queue, 0 means infinity. +*/ +MESA_lqueue_head MESA_lqueue_create(int thread_safe, long max_item_num); + +/* + attention: + The follow two functions is get some value of queue in a moment, + however, the value you got is not exactly, + because it's maybe changed immediately by other thread when this functions is return. +*/ +long MESA_lqueue_get_mem_used(MESA_lqueue_head head); +long MESA_lqueue_get_count(MESA_lqueue_head head); + + +/* + args description: + [IN]: + lq_head : the handler of MESA_lqueue. + + [OUT]: + data : receive buffer. + + [IN && OUT]: + data_len: + is value-result argument, like "addrlen of recvfrom(2)", + the caller should initialize the size of the 'data', + will modified on return to indicate the actual size of the queue item. + +*/ +int MESA_lqueue_read_head(MESA_lqueue_head lq_head, void *data, long *data_len); +int MESA_lqueue_get_head(MESA_lqueue_head lqhead, void *data, long *data_len); + +/* + if return value of "cb" is 0, the behaviour is like MESA_lqueue_read_head(), + else if return value of "cb" is not 0, the behaviour is like MESA_lqueue_get_head(). +*/ +int MESA_lqueue_detect_get_head(MESA_lqueue_head lq_head, MESA_lqueue_cb_t cb, void *data, long *data_len, void *cb_arg); +int MESA_lqueue_get_tail(MESA_lqueue_head lq_head, void *data, long *data_len); + +int MESA_lqueue_join_head(MESA_lqueue_head lq_head, const void *data, long data_len); +int MESA_lqueue_join_tail(MESA_lqueue_head lq_head, const void *data, long data_len); + + +/* these functions features same with above no "try", + except shall return immediately, in other word is "Non-block mode"! + */ +int MESA_lqueue_try_read_head(MESA_lqueue_head lq_head, void *data, long *data_len); +int MESA_lqueue_try_get_head(MESA_lqueue_head lq_head, void *data, long *data_len); +int MESA_lqueue_try_get_tail(MESA_lqueue_head lq_head, void *data, long *data_len); +int MESA_lqueue_try_join_head(MESA_lqueue_head lq_head, const void *data, long data_len); +int MESA_lqueue_try_join_tail(MESA_lqueue_head lq_head, const void *data, long data_len); + + +void MESA_lqueue_destroy(MESA_lqueue_head head, MESA_lqueue_cb_t cb, void *cb_arg); + +const char *MESA_lqueue_strerror(MESA_queue_errno_t error_num); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/include/MESA/MESA_prof_load.h b/src/include/MESA/MESA_prof_load.h new file mode 100644 index 0000000..84c5deb --- /dev/null +++ b/src/include/MESA/MESA_prof_load.h @@ -0,0 +1,179 @@ +#ifndef SLIB_LOADPROF_H +#define SLIB_LOADPROF_H +#include <sys/types.h> + +#ifdef __cplusplus +extern "C" { +#endif + + +// Read in specified integer value +// +// Return: +// 0 : success +// < 0 : error, val is set to default +int MESA_load_profile_int_def( + const char *file, // [IN] initialization file path + const char *section, // [IN] section name in initialization file + const char *key, // [IN] keyword name in initialization file + int *val, // [OUT] returned value + const int dval); // [IN] default value + + + +// Read in specified integer value +// +// Return: +// 0 : success +// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error +// -2 : error ,the val if out of range +int MESA_load_profile_int_nodef( + const char *file, // [IN] initialization file path + const char *section, // [IN] section name in initialization file + const char *key, // [IN] keyword name in initialization file + int *val); // [OUT] returned value + + + + +// Read in specified unsigned integer value +// +// Return: +// 0 : success +// < 0 : error, val is set to default +int MESA_load_profile_uint_def( + const char *file, // [IN] initialization file path + const char *section, // [IN] section name in initialization file + const char *key, // [IN] keyword name in initialization file + unsigned int *val, // [OUT] returned value + const unsigned int dval); // [IN] default value + + + +// Read in specified unsigned integer value +// +// Return: +// 0 : success +// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error +// -2 : error ,the val if out of range +int MESA_load_profile_uint_nodef( + const char *file, // [IN] initialization file path + const char *section, // [IN] section name in initialization file + const char *key, // [IN] keyword name in initialization file + unsigned int *val); // [OUT] returned value + + + +// Read in specified short integer value +// +// Return: +// 0 : success +// < 0 : error, val is set to default +int MESA_load_profile_short_def( + const char *file, // [IN] initialization file path + const char *section, // [IN] section name in initialization file + const char *key, // [IN] keyword name in initialization file + short *val, // [OUT] returned value + const short dval); // [IN] default value + + + +// Read in specified short integer value +// +// Return: +// 0 : success +// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error +// -2 : error ,the val if out of range +int MESA_load_profile_short_nodef( + const char *file, // [IN] initialization file path + const char *section, // [IN] section name in initialization file + const char *key, // [IN] keyword name in initialization file + short *val); // [OUT] returned value + + + +// Read in specified string value, +// if value string is too long to return, extra chars truncated. +// prefix/postfix space chars cutted, +// space chars: ' ', '\t' '\n' '\r' +// +// Return: +// >= 0 : length of val +// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error + +int MESA_load_profile_string_nodef( + const char *file, // [IN] initialization file path + const char *section, // [IN] section name in initialization file + const char *key, // [IN] keyword name in initialization file + char *str, // [OUT] returned string + const size_t size); // [IN] buffer size(bytes) + + + +// Read in specified string value, +// if value string is too long to return, extra chars truncated. +// prefix/postfix space chars cutted, +// space chars: ' ', '\t' '\n' '\r' +// +// Return: +// >= 0 : length of val +// < 0 : error, str is set to default +int MESA_load_profile_string_def( + const char *file, // [IN] initialization file path + const char *section, // [IN] section name in initialization file + const char *key, // [IN] keyword name in initialization file + char *str, // [OUT] returned string + const size_t size, // [IN] buffer size(bytes) + const char *dstr); // [IN] default string + + + +//read ips from config file +//return : +// >=0 : success,return the number of ip read from file successfully +// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error +// -2 : error,invalid ip + +#if 0 +int MESA_load_profile_ipset( + const char *file, // [IN] initialization file path + const char *section, // [IN] section name in initialization file + const char *key, // [IN] keyword name in initialization file + const size_t size, // [IN] the size of memory ips point,it must equel or greater than ip_num*sizeof(unsigned int) + unsigned int *ipset); // [OUT] return ipset network bytes order + +// Write the a int into specified position of the config file,the position is decided by section and key +// Return: +// >= 0 : success +// -1 : failed to write profile,maybe fopen failed, or malloc failed +int MESA_write_profile_int( + const char *file, // [IN] initialization file path + const char *section, // [IN] section name in initialization file + const char *key, // [IN] keyword name in initialization file + const int value); // [IN] the integer need write + +// Write the a float into specified position of the config file,the position is decided by section and key +// Return: +// >= 0 : success +// -1 : failed to write profile,maybe fopen failed, or malloc failed +int MESA_write_profile_float( + const char *file, // [IN] initialization file path + const char *section, // [IN] section name in initialization file + const char *key, // [IN] keyword name in initialization file + const float value); // [IN] the float need write + +// Write the a string into specified position of the config file,the position is decided by section and key +// Return: +// >= 0 : success +// -1 : failed to write profile,maybe fopen failed, or malloc failed +int MESA_write_profile_string( + const char *file, // [IN] initialization file path + const char *section, // [IN] section name in initialization file + const char *key, // [IN] keyword name in initialization file + const char *value); // [IN] the string need write +#endif +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef SLIB_LOADPROF_H */ diff --git a/src/include/MESA/asmis_log.h b/src/include/MESA/asmis_log.h new file mode 100644 index 0000000..b04dc89 --- /dev/null +++ b/src/include/MESA/asmis_log.h @@ -0,0 +1,73 @@ +#ifndef __ASMIS_LOG_H +#define __ASMIS_LOG_H +#ifndef __cplusplus +#error("This file should be compiled with C++ compiler") +#endif +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + + +//#include <support/thread_safe.h> + +#define ASMIS_KEY 0x01 +#define ASMIS_ALARM 0x02 +#define ASMIS_OTHER 0x03 + +#define ASMIS_LOGMSG_TIMEOUT 300 //second +#define ASMIS_LOGMSG_LENGTH 40000 //bytes + +//ϵͳʹ�ö˿���Ϣ�ṹ�� +struct info_port_used { + unsigned short nPort; + unsigned char nProtocolType; + unsigned char nPortType; + char sPortDesc[128]; +}; + +//ϵͳʵʱ������Ϣ�ṹ�� +struct info_rtd_flow { + char sValType[32]; + char sBDType[32]; + time_t nRTTS; + int nDuration; + unsigned long long nValue; +}; + +//ϵͳ���Ը�����Ϣ�ṹ�� +struct info_policy_update { + char sName[128]; + char sDesc[256]; + time_t nUpdateTime; + char sVersion[33]; + int nTotal; + int nNew; + int nDelete; + int nUpdate; + int nSize; +}; + +//NetLog��ʼ�� +void* asmis_log_Init(const char *pProcName); +//�Ǽdz���汾��Ϣ +int asmis_log_AppVer(void* netlog_handle,const char *pVersionTime, const char *pVersionNO, const char *pVersionDesc); +//ϵͳ������־ +int asmis_log_LogMsg(void* netlog_handle,const char *pMsg, const char *pNo, int nAlarmType); +//�Ǽ�ϵͳʹ�ö˿� +int asmis_log_PortUsed(void* netlog_handle,struct info_port_used *info, int nPort); +//�Ǽ�ϵͳʵʱ������Ϣ +int asmis_log_RtdFlow(void* netlog_handle,time_t nStartTime, int nDuration, struct info_rtd_flow *info, int nFlow); +//�Ǽ�ϵͳ��ʼ���� +int asmis_log_RunStart(void* netlog_handle,int nContiRun); +//�Ǽ�ϵͳֹͣ��Ϣ +int asmis_log_RunStop(void* netlog_handle,int nContiRun); +//������Ϣ +int asmis_log_HeartBeat(void* netlog_handle,const char *pMsg); +//���Ը�����Ϣ +int asmis_log_Policy(void* netlog_handle,struct info_policy_update *info, int nPolicy); + +#endif diff --git a/src/include/MESA/field_stat2.h b/src/include/MESA/field_stat2.h new file mode 100644 index 0000000..548a27f --- /dev/null +++ b/src/include/MESA/field_stat2.h @@ -0,0 +1,67 @@ +#ifndef H_SCREEN_STAT_H_INCLUDE +#define H_SCREEN_STAT_H_INCLUDE +#include <stdio.h> + +#ifndef __cplusplus +#error("This file should be compiled with C++ compiler") +#endif + +enum field_dsp_style_t +{ + FS_STYLE_FIELD=0, + FS_STYLE_COLUMN, + FS_STYLE_LINE, + FS_STYLE_STATUS +}; +enum field_calc_algo +{ + FS_CALC_CURRENT=0, + FS_CALC_SPEED +}; +enum field_op +{ + FS_OP_ADD=1, + FS_OP_SET +}; + + +typedef void* screen_stat_handle_t; + +enum FS_option +{ + OUTPUT_DEVICE, //VALUE is a const char*, indicate a file path string, SIZE = strlen(string+'\0')+1.DEFAULT:output to stdout. + PRINT_MODE, //VALUE is an interger,1:Rewrite ,2: Append. SIZE=4,DEFALUT:REWRITE. + STAT_CYCLE, //VALUE is an interger idicate interval seconds of every output, SIZE=4 ,DEFUALT:2 seconds. + PRINT_TRIGGER, //VALUE is an interger,1:Do print,0: Don't print.SIZE=4.DEFAULT:1. + CREATE_THREAD, //VALUE is an interger,1: Create a print thread,0:not create,output by call passive_output function, + //and the STAT_CYCLE is meaningless.SIZE=4,DEFAULT:0. + ID_INVISBLE, //value is field_id/status_id/column_id, not output this string, SIZE=4,DEFAULT: shutdown NO one. + FLUSH_BY_DATE, //value is 1(ture) or 0(false),SIZE=4,DEFAULT: Do not flush by date. + APP_NAME, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1. DEFAULT is "?". + STATS_SERVER_IP, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1. No DEFAULT. + STATS_SERVER_PORT, //VALUE is a unsigned short, host order, SIZE= sizeof(unsigned short). No DEFAULT. + STATS_ACC_VAL, //value is field_id/status_id, in stats server model, will output accmulate value, SIZE=4,DEFAULT: None. +}; + +//Always success. +screen_stat_handle_t FS_create_handle(void); + +int FS_set_para(screen_stat_handle_t handle, enum FS_option type,const void* value,int size); +void FS_start(screen_stat_handle_t handle); +void FS_stop(screen_stat_handle_t* handle); + +//return field_id/line_id/column_id greater than zero if success,return an interger less than zero if failed. +//should NOT include "|:\n\r.\t<>[]#!@"or space in the parameter name. +int FS_register(screen_stat_handle_t handle,enum field_dsp_style_t style,enum field_calc_algo calc_type,const char* name); + +//numerator_id and denominator_id must be column/field/status style. +//scaling: negative value: zoom in; positive value: zoom out; +int FS_register_ratio(screen_stat_handle_t handle,int numerator_id,int denominator_id,int scaling,enum field_dsp_style_t style,enum field_calc_algo calc_type,const char* name); + +//id: when id's type is FIELD , column_id is ignore. +int FS_operate(screen_stat_handle_t handle,int id,int column_id,enum field_op op,long long value); + +void FS_passive_output(screen_stat_handle_t handle); + +#endif + diff --git a/src/include/avlsdk/AVLSDK_conf_idx.h b/src/include/avlsdk/AVLSDK_conf_idx.h new file mode 100644 index 0000000..3127f28 --- /dev/null +++ b/src/include/avlsdk/AVLSDK_conf_idx.h @@ -0,0 +1,173 @@ +#ifndef __AVLSDK_CONF_IDX_H__ +#define __AVLSDK_CONF_IDX_H__ + +#define CFG_ITEM_MAX_LIMIT (128) + +#define CFG_STR_MODULE_PATH (0) +#define CFG_STR_DATA_PATH (1) +#define CFG_STR_TMP_PATH (2) +#define CFG_STR_LOG_PATH (3) + +#define CFG_FLAG_SHELL_RECG_LOAD (4) +#define CFG_FLAG_SFX_DETECT_LOAD (5) +#define CFG_FLAG_INFECT_DETECT_LOAD (6) +#define CFG_FLAG_COMM_DETECT_LOAD (7) +#define CFG_FLAG_SEC_DETECT_LOAD (8) +#define CFG_FLAG_PEP_DETECT_LOAD (9) +#define CFG_FLAG_HD_DETECT_LOAD (10) +#define CFG_FLAG_STREAM_DETECT_LOAD (11) +#define CFG_FLAG_OPC_DETECT_LOAD (12) +#define CFG_FLAG_EXPLOIT_DETECT_LOAD (13) +#define CFG_FLAG_SCRIPT_DETECT_LOAD (14) +#define CFG_FLAG_VCS2S_DETECT_LOAD (15) +#define CFG_FLAG_PATH_FILTER_LOAD (16) +#define CFG_FLAG_UNITARINESS_LOAD (17) +#define CFG_FLAG_SPLIT_SCRIPT_LOAD (18) +#define CFG_FLAG_SPLIT_PE_LOAD (19) +#define CFG_FLAG_APACK_LOAD (20) +#define CFG_FLAG_STATIC_UPK_LOAD (21) +#define CFG_FLAG_AEML_LOAD (22) + +#define CFG_FLAG_LOG_ENABLE (23) +#define CFG_FLAG_ALL_MOD_ANALYSE (24) +#define CFG_INT_MAX_SCAN_LEVEL_LIMIT (25) +#define CFG_INT_MAX_FILE_SIZE_LIMIT (26) + +#define CFG_FLAG_SHELL_RECG_ENABLE (27) + +#define CFG_FLAG_SFX_DETECT_ENABLE (28) + +#define CFG_FLAG_INFECT_DETECT_ENABLE (29) + +#define CFG_FLAG_COMM_DETECT_ENABLE (30) + +#define CFG_FLAG_SEC_DETECT_ENABLE (31) + +#define CFG_FLAG_PEP_DETECT_ENABLE (32) + +#define CFG_FLAG_HD_DETECT_ENABLE (33) + +#define CFG_FLAG_STREAM_DETECT_ENABLE (34) + +#define CFG_FLAG_OPC_DETECT_ENABLE (35) + +#define CFG_FLAG_EXPLOIT_DETECT_ENABLE (36) + +#define CFG_FLAG_SCRIPT_DETECT_ENABLE (37) +#define CFG_INT_SCAN_SCRIPT_MAX_SIZE (38) + +#define CFG_FLAG_PATH_FILTER_ENABLE (39) + +#define CFG_FLAG_UNITARINESS_ENABLE (40) +#define CFG_INT_UNITARINESS_EOP_MAX_DASM_COUNT (41) +#define CFG_INT_UNITARINESS_EOP_RECURE_LAYER (42) + +#define CFG_FLAG_SPLIT_SCRIPT_ENABLE (43) + +#define CFG_FLAG_SPLIT_PE_ENABLE (44) +#define CFG_FLAG_SPLIT_PE_OVERLAY_ENABLE (45) +#define CFG_FLAG_SPLIT_PE_RES_ENABLE (46) +#define CFG_INT_SPLIT_PE_RES_MIN_ITEM_SIZE (47) +#define CFG_INT_SPLIT_PE_OVERLAY_MAX_SEARCH (48) +#define CFG_INT_SPLIT_PE_OVERLAY_MIN_SIZE (49) + +#define CFG_FLAG_APACK_ENABLE (50) +#define CFG_INT_APACK_MAX_ARCHIVE_SIZE (51) +#define CFG_INT_APACK_MAX_FILE_NUM (52) +#define CFG_INT_APACK_MAX_FILE_SIZE (53) +#define CFG_INT_APACK_RECURE_LAYER (54) +#define CFG_INT_APACK_MAX_COMPR_SCALE (55) +#define CFG_INT_APACK_TIMEOUT (56) +#define CFG_FLAG_APACK_RPTBOMB (57) +#define CFG_INT_APACK_USE_MAX_MEMORY_SIZE (58) + +#define CFG_FLAG_STATIC_UPK_ENABLE (59) + +#define CFG_FLAG_AEML_ENABLE (60) + +#define CFG_FLAG_VCS2S_ENABLE (61) +#define CFG_INT_VCS2S_LEVEL (62) +#define CFG_INT_VCS2S_CHECKMODE (63) + +#define CFG_FLAG_FBLOOM_DETECT_LOAD (64) +#define CFG_FLAG_FBLOOM_DETECT_ENABLE (65) + +#define CFG_FLAG_KEXPLOIT_DETECT_LOAD (66) +#define CFG_FLAG_KEXPLOIT_DETECT_ENABLE (67) + +#define CFG_FLAG_SUF_LOAD (68) +#define CFG_FLAG_SUF_ENABLE (69) + +#define CFG_FLAG_SUFB_LOAD (70) +#define CFG_FLAG_SUFB_ENABLE (71) + +#define CFG_FLAG_VM_DETECT_ENABLE (72) + +#define CFG_FLAG_CLOUD_DETECT_LOAD (73) +#define CFG_FLAG_CLOUD_DETECT_ENABLE (74) +#define CFG_STR_CLOUD_HOST (75) +#define CFG_INT_CLOUD_CONNECT_TIMEOUT (76) +#define CFG_INT_CLOUD_DETECT_TIMEOUT (77) + +#define CFG_FLAG_BOL_DETECT_LOAD (78) +#define CFG_FLAG_BOL_DETECT_ENABLE (79) + +#define CFG_FLAG_MSCRIPT_DETECT_LOAD (80) +#define CFG_FLAG_MSCRIPT_DETECT_ENABLE (81) + +#define CFG_FLAG_ELF_DETECT_LOAD (82) +#define CFG_FLAG_ELF_DETECT_ENABLE (83) + +#define CFG_FLAG_CLOUD_WAIT_BLOCK (84) +#define CFG_INT_CLOUD_MAX_QUEUE_SIZE (85) +#define CFG_FLAG_CLOUD_DETECT_DERIVE_DATA (86) + +#define CFG_STR_LICENSE_PATH (87) + +#define CFG_FLAG_YARA_DETECT_LOAD (88) +#define CFG_FLAG_YARA_DETECT_ENABLE (89) + +#define CFG_FLAG_MACRO_DETECT_LOAD (90) +#define CFG_FLAG_MACRO_DETECT_ENABLE (91) + +#define CFG_FLAG_ANDROID_DETECT_LOAD (92) +#define CFG_FLAG_ANDROID_DETECT_ENABLE (93) + +#define CFG_FLAG_GEN_HASH_DETECT_LOAD (94) +#define CFG_FLAG_GEN_HASH_DETECT_ENABLE (95) + +#define CFG_INT_SPLIT_SCRIPT_MAX_ITEMS_COUNT (96) +#define CFG_INT_SPLIT_SCRIPT_MIN_SCRIPT_SIZE (97) + +#define CFG_FLAG_VCS3S_DETECT_LOAD (98) +#define CFG_FLAG_VCS3S_ENABLE (99) + +#define CFG_FLAG_NSIS_DETECT_LOAD (100) +#define CFG_FLAG_NSIS_DETECT_ENABLE (101) + +#define CFG_FLAG_SWF_DETECT_LOAD (102) +#define CFG_FLAG_SWF_DETECT_ENABLE (103) + +#define CFG_FLAG_SPLIT_SWF_LOAD (104) +#define CFG_FLAG_SPLIT_SWF_ENABLE (105) + +#define CFG_FLAG_HEML_DETECT_LOAD (106) +#define CFG_FLAG_HEML_DETECT_ENABLE (107) + +#define CFG_FLAG_REG_DETECT_LOAD (108) +#define CFG_FLAG_REG_DETECT_ENABLE (109) + +#define CFG_FLAG_GSCPT_DETECT_LOAD (110) +#define CFG_FLAG_GSCPT_DETECT_ENABLE (111) + +#define CFG_FLAG_ELF_SFX_DETECT_LOAD (112) +#define CFG_FLAG_ELF_SFX_DETECT_ENABLE (113) + +#define CFG_FLAG_DOH_DETECT_LOAD (114) +#define CFG_FLAG_DOH_DETECT_ENABLE (115) + +#define CFG_FLAG_MACRO_DETECT_HEUR_ENABLE (116) + +#endif // __AVLSDK_CONF_IDX_H__ + + diff --git a/src/include/avlsdk/AVLSDK_rpt_idx.h b/src/include/avlsdk/AVLSDK_rpt_idx.h new file mode 100644 index 0000000..8888b31 --- /dev/null +++ b/src/include/avlsdk/AVLSDK_rpt_idx.h @@ -0,0 +1,55 @@ +#ifndef __AVLSDK_RPT_IDX_H__ +#define __AVLSDK_RPT_IDX_H__ + +#define RPT_ITEM_MAX_LIMIT (128) + +#define RPT_IDX_OBJ_DESCRIPTION (0) +#define RPT_IDX_MALWARE_ID (1) +#define RPT_IDX_ANALYSER (2) + +#define RPT_IDX_FILE_FORMAT_ID (3) +#define RPT_IDX_SHELL_ID (4) +#define RPT_IDX_INFECTED_ID (5) +#define RPT_IDX_COMM_DETECT_ID (6) +#define RPT_IDX_PEP_DETECT_ID (7) +#define RPT_IDX_EXPLOIT_DETECT_ID (8) +#define RPT_IDX_SCRIPT_DETECT_ID (9) +#define RPT_IDX_OPC_DETECT_ID (10) +#define RPT_IDX_PATH_FILTER_ID (11) +#define RPT_IDX_EMC_ID (12) +#define RPT_IDX_VCS2S_DETECT_ID (13) +#define RPT_IDX_VCS2S_DETAIL_LOW32 (14) +#define RPT_IDX_VCS2S_DETAIL_HIGH32 (15) +#define RPT_IDX_VCS2S_RESULT_DETAIL (16) +#define RPT_IDX_VCS2S_THREAT_LEVEL (17) +#define RPT_IDX_SEC_DETECT_ID (18) +#define RPT_IDX_HEUR_FORMAT_ID (19) +#define RPT_IDX_HD_DETECT_ID (20) +#define RPT_IDX_STREAM_DETECT_ID (21) +#define RPT_IDX_SFX_DETECT_ID (22) +#define RPT_IDX_FBLOOM_DETECT_ID (23) +#define RPT_IDX_KEXPLOIT_DETECT_ID (24) +#define RPT_IDX_SUF_DETECT_ID (25) +#define RPT_IDX_CLOUD_DETECT_ID (26) +#define RPT_IDX_BOL_DETECT_ID (27) +#define RPT_IDX_MSCRIPT_DETECT_ID (28) +#define RPT_IDX_ELF_DETECT_ID (29) +#define RPT_IDX_YARA_DETECT_ID (30) +#define RPT_IDX_MACRO_DETECT_ID (31) +#define RPT_IDX_ANDROID_DETECT_ID (32) +#define RPT_IDX_GEN_HASH_DETECT_ID (33) +#define RPT_IDX_VCS3S_DETECT_ID (34) +#define RPT_IDX_NSIS_DETECT_ID (35) +#define RPT_IDX_SWF_DETECT_ID (36) +#define RPT_IDX_HEML_DETECT_ID (37) +#define RPT_IDX_REG_DETECT_ID (38) +#define RPT_IDX_HSCPT_DETECT_ID (39) +#define RPT_IDX_ARCHIVE_DETECT_ID (40) +#define RPT_IDX_GSCPT_DETECT_ID (41) +#define RPT_IDX_DOH_DETECT_ID (42) + +#define RPT_IDX_SKIPPED_REASON (100) + +#endif // __AVLSDK_RPT_IDX_H__ + + diff --git a/src/include/avlsdk/ID2Name_interface.h b/src/include/avlsdk/ID2Name_interface.h new file mode 100644 index 0000000..c45ac09 --- /dev/null +++ b/src/include/avlsdk/ID2Name_interface.h @@ -0,0 +1,42 @@ +#ifndef __ID_NAME_INTERFACE_H__ +#define __ID_NAME_INTERFACE_H__ + +#ifdef __cplusplus +extern "C"{ +#endif + +typedef void *(*pMalloc)(int); +typedef void (*pFree)(void*); +typedef void *(*pRealloc)(void*,int); +typedef int (*pSize)(void*); +typedef int (*pRoundup)(int); +typedef int (*pInit)(void*); +typedef void (*pShutdown)(void*); + +typedef struct _nt_sys_fn +{ + pMalloc nt_malloc; + pFree nt_free; + pRealloc nt_realloc; + pSize nt_size; + pRoundup nt_roundup; + pInit nt_init; + pShutdown nt_shutdown; + void *param; +} NT_SYS_FN, *P_NT_SYS_FN; + +long AVL_NTranser_Init(const char *path, void **handle); + +long AVL_NTranser_Init_Ex(const char *path, P_NT_SYS_FN sys_fn, void **handle); + +long AVL_NTranser_QueryNameByID(void *handle, const char *mod_name, long id, unsigned char *buf, unsigned long size); + +void AVL_NTranser_Release(void *handle); + +#ifdef __cplusplus +} +#endif + +#endif // __ID_NAME_INTERFACE_H__ + + diff --git a/src/include/avlsdk/engine.h b/src/include/avlsdk/engine.h new file mode 100644 index 0000000..5768687 --- /dev/null +++ b/src/include/avlsdk/engine.h @@ -0,0 +1,292 @@ +#ifndef __AVLSDK_INTERFACE_H__ +#define __AVLSDK_INTERFACE_H__ + +#ifdef __cplusplus +extern "C"{ +#endif + +// Macros about continue or abort +#define OD_CONTINUE (1) +#define OD_ABORT (2) + +#define CUR_ENGINE_VER (0x03000301) +#define CUR_ENGINE_VER_STR ("3.0.3.1") + +// Data type + +// Data environment type +#define ET_NETWORK (1) +#define ET_DESKTOP (2) + +// Sub module names +#define SMN_FILE_FMT ("AIFilFmt") +#define SMN_SHELL_RECOGNIZE ("AIPack") +#define SMN_SFX_DETECT ("AISfxArc") +#define SMN_INFECTED ("ASVirus") +#define SMN_BOL_DETECT ("ASBOL") +#define SMN_COMMON_DETECT ("ASCommon") +#define SMN_MALWS_DETECT ("ASMalwS") +#define SMN_MALWE_DETECT ("ASMalwE") +#define SMN_MALWFH_DETECT ("ASMalwFH") +#define SMN_MALWHS_DETECT ("ASMalwHS") +#define SMN_KEXPLOIT_DETECT ("ASKExplt") +#define SMN_EXPLOIT_DETECT ("ASExplot") +#define SMN_SCRIPT_DETECT ("ASScript") +#define SMN_MALWB_DETECT ("ASMalwB") +#define SMN_VCS2_STATIC ("ASVCS2S") +#define SMN_SPLIT_SCRIPT ("APSScrpt") +#define SMN_UNIT_EOP ("APUnitEP") +#define SMN_SPLIT_PE ("APSPE") +#define SMN_ARCHIVE ("APUnArc") +#define SMN_UNPACK_STATIC ("APUnPack") +#define SMN_SPLIT_EML ("APSMail") +#define SMN_SUF ("AWSuf") +#define SMN_SUF_DETECT ("ASSuf") +#define SMN_CLOUD_DETECT ("ASCloud") +#define SMN_MSCRIPT_DETECT ("ASMScrip") +#define SMN_ELF_DETECT ("ASELF") +#define SMN_YARA_DETECT ("ASYR") +#define SMN_MACRO_DETECT ("ASMacro") +#define SMN_ANDROID_DETECT ("ASDroid") +#define SMN_GEN_HASH_DETECT ("ASMalwGH") +#define SMN_VCS3_STATIC ("ASVCS3S") +#define SMN_MALWNS_DETECT ("ASMalwNS") +#define SMN_SWF_DETECT ("ASSwf") +#define SMN_SPLIT_SWF ("APUnSwf") +#define SMN_MALWHM_DETECT ("ASMalwHM") +#define SMN_REG_DETECT ("ASMalwRG") +#define SMN_MALWSC_DETECT ("ASMalwSC") +#define SMN_HEML_DETECT ("ASEMLH") +#define SMN_HSCPT_DETECT ("ASScptH") +#define SMN_ELF_SFX_DETECT ("AIESfxAc") +#define SMN_DOH_DETECT ("ASDOH") + +typedef void *(*P_AVL_MALLOC)(unsigned long size); +typedef void (*P_AVL_FREE)(void *p_handle); +typedef void *(*P_AVL_EXEC_MALLOC)(int size); +typedef void (*P_AVL_EXEC_FREE)(void *buf, int size); + +typedef void *(*P_AVL_FOPEN)(const char *path, const char *mode); +typedef long (*P_AVL_FREAD)(void *buf, long size, long count, void *handle); +typedef long (*P_AVL_FWRITE)(void *buf, long size, long count, void *handle); +typedef long (*P_AVL_FTELL)(void *handle); +typedef int (*P_AVL_FFLUSH)(void *handle); +typedef int (*P_AVL_FCLOSE)(void *handle); +typedef int (*P_AVL_FSEEK)(void *handle, long offset, int whence); + +typedef struct _sys_fn_set +{ + P_AVL_MALLOC sys_malloc; + P_AVL_FREE sys_free; + P_AVL_EXEC_MALLOC sys_exec_malloc; + P_AVL_EXEC_FREE sys_exec_free; + P_AVL_FOPEN sys_fopen; + P_AVL_FREAD sys_fread; + P_AVL_FWRITE sys_fwrite; + P_AVL_FTELL sys_ftell; + P_AVL_FFLUSH sys_fflush; + P_AVL_FCLOSE sys_fclose; + P_AVL_FSEEK sys_fseek; +} SYS_FN_SET, *P_SYS_FN_SET; + +typedef struct +{ + unsigned long obj_ver; // version of this structure + unsigned long obj_type; // data type + unsigned long evro_type; // environment type + unsigned char *buf; // pointer of data buffer + unsigned long size; // size of valid data + unsigned char obj_des[4096]; // data description +} OBJ_PROVIDER, *P_OBJ_PROVIDER; + +/*************************************************************************************************\ + * Function : Engine will call this callback function when it finishes scanning a object + * Param : p_op the object provider pointer + * : p_rpt_handle the handle of result report + * p_param transfered to engine by OBJ_DISPOSER::p_rpt_param + * + * Return : Undefined + * Note : This callback function will be called only if engine reports the scanning result +\*************************************************************************************************/ +typedef long (*P_OBJ_DISPOSER_CALLBACK)(P_OBJ_PROVIDER p_op, void *p_rpt_handle, void *p_param); + +/*************************************************************************************************\ + * Function : Engine will call this callback function when it needs to know continue or not + * Param : p_param transfered to engine by OBJ_DISPOSER::p_rpt_param + * + * Return : OD_CONTINUE or OD_ABORT +\*************************************************************************************************/ +typedef long (*P_QUERY_CONTINUE_CALLBACK)(void *p_param); + +typedef struct +{ + P_OBJ_DISPOSER_CALLBACK rpt_callback; + void *p_rpt_param; + P_QUERY_CONTINUE_CALLBACK query_continue_callback; + void *p_qc_param; +} OBJ_DISPOSER, *P_OBJ_DISPOSER; + +typedef struct +{ + unsigned long total_db_item_count; + char db_time_stamp[32]; +} DB_INFO, *P_DB_INFO; + +/*************************************************************************************************\ + * Function : Create a new instance of engine + * Param : ppEngine the engine handle returned + * + * Return : Error code +\*************************************************************************************************/ +long AVL_SDK_CreateInstance(void **ppEngine); + +/*************************************************************************************************\ + * Function : Release handle of engine instance + * Param : pEngine the engine handle + * + * Return : Error code +\*************************************************************************************************/ +long AVL_SDK_Release(void *pEngine); + +/*************************************************************************************************\ + * Function : Set the functions of system(malloc etc.) + * Param : sys_fn the pointer of SYS_FN_SET + * + * Return : Error code +\*************************************************************************************************/ +long AVL_SDK_SetSysFn(P_SYS_FN_SET sys_fn); + +/*************************************************************************************************\ + * Function : Load a template file of configuration + * Param : pEngine the engine handle + * szFilename the full path of configuration file + * + * Return : Error code +\*************************************************************************************************/ +long AVL_SDK_LoadConfigFile(void *pEngine, char *szFilename); + +/*************************************************************************************************\ + * Function : Set an int value to engine + * Param : pEngine the engine handle + * pCfgIdx index of configuration + * lValue the value to be set + * + * Return : Error code +\*************************************************************************************************/ +long AVL_SDK_SetConfigInt(void *pEngine, long CfgIdx, long lValue); + +/*************************************************************************************************\ + * Function : Set an string value to engine + * Param : pEngine the engine handle + * pCfgIdx index of configuration + * pValue the value to be set + * + * Return : Error code +\*************************************************************************************************/ +long AVL_SDK_SetConfigString(void *pEngine, long CfgIdx, const char *pValue); + +/*************************************************************************************************\ + * Function : Get an int value from engine + * Param : pEngine the engine handle + * pCfgIdx index of configuration + * pValue the buffer to store the value + * + * Return : Error code +\*************************************************************************************************/ +long AVL_SDK_GetConfigInt(void *pEngine, long CfgIdx, long *pValue); + +/*************************************************************************************************\ + * Function : Get an string value from engine + * Param : pEngine the engine handle + * pCfgIdx index of configuration + * Buf the buffer to store the value + * BufLen the length of the buffer + * + * Return : Error code +\*************************************************************************************************/ +long AVL_SDK_GetConfigString(void *pEngine, long CfgIdx, char *Buf, long BufLen); + +/*************************************************************************************************\ + * Function : Initialize the engine handle based on the configuration + * Param : pEngine the engine handle + * pVerificationCode verification code + * + * Return : Error code + * Note : If initialization failes, engine will release this instance automatically +\*************************************************************************************************/ +long AVL_SDK_InitInstance(void *pEngine, const void* pVerificationCode); + +/*************************************************************************************************\ + * Function : Scan data + * Param : pEngine the engine handle + * pObj the pointer of OBJ_PROVIDER structure + * pObjDisposer the pointer of OBJ_DISPOSER structure + * + * Return : Error code +\*************************************************************************************************/ +long AVL_SDK_Scan(void *pEngine, P_OBJ_PROVIDER pObj, P_OBJ_DISPOSER pObjDisposer); + +/*************************************************************************************************\ + * Function : Query the result report + * Param : pEngine the engine handle + * pRptHandle the handle of report + * key the index of report + * value the buffer to get report + * + * Return : Error code +\*************************************************************************************************/ +long AVL_SDK_QueryReportInt(void *pEngine, void *pRptHandle, unsigned long key, long *value); + +/*************************************************************************************************\ + * Function : Query the result report + * Param : pEngine the engine handle + * pRptHandle the handle of report + * key the index of report + * value the pointer to string report + * + * Return : Error code +\*************************************************************************************************/ +long AVL_SDK_QueryReportStr(void *pEngine, void *pRptHandle, unsigned long key, unsigned char **value); + +/*************************************************************************************************\ + * Function : Query the library info + * Param : pEngine the engine handle + * pDBInfo the pointer of DB_INFO structure + * + * Return : Error code +\*************************************************************************************************/ +long AVL_SDK_QueryDBInfo(void *pEngine, P_DB_INFO pDBInfo); + +/*************************************************************************************************\ + * Function : Reload the library + * Param : pEngine the engine handle + * + * Return : Error code +\*************************************************************************************************/ +long AVL_SDK_ReloadDB(void *pEngine); + +/*************************************************************************************************\ + * Function : Get engine version + * Param : buf the buffer to store the version string + * len the buffer length + * + * Return : Error code +\*************************************************************************************************/ +long AVL_SDK_GetCurVersion(unsigned char *buf, unsigned long len); + +/*************************************************************************************************\ + * Function : Get license expiration date + * Param : pEngine the engine handle + * : buf the buffer to store the date string + * len the buffer length + * + * Return : Error code +\*************************************************************************************************/ +long AVL_SDK_GetLicenseExpDate(void *pEngine, unsigned char *buf, unsigned long len); +#ifdef __cplusplus +} +#endif + +#endif // __AVLSDK_INTERFACE_H__ + + diff --git a/src/include/avlsdk/error_code.h b/src/include/avlsdk/error_code.h new file mode 100644 index 0000000..63715b2 --- /dev/null +++ b/src/include/avlsdk/error_code.h @@ -0,0 +1,30 @@ +#ifndef ERROR_CODE_H +#define ERROR_CODE_H + +// �ɹ� +#define ERR_SUCCESS 0 // + +// �����쳣 +#define ERR_UNKNOWN -1 +#define ERR_INCORRECT_PARAM -2 +#define ERR_NO_ENOUGH_MEM -3 +#define ERR_BAD_LICENSE -4 +#define ERR_BAD_AUTH_CODE -5 +#define ERR_BAD_ENGINE_VER -6 +#define ERR_BAD_DATABASE -7 +#define ERR_INIT_COMPONENT_FAILED -8 +#define ERR_MISS_IMPORTANT_MOD_FILE -9 +#define ERR_MISS_IMPORTANT_DATA_FILE -10 +#define ERR_BAD_WORKING_PATH -11 +#define ERR_LOAD_CONFIG -12 +#define ERR_SET_CONFIG -13 +#define ERR_GET_CONFIG -14 +#define ERR_SCAN_FAILED -15 + +// ������ +#define ERR_MISS_MOD_FILE 1 +#define ERR_USER_ABORT 2 // �û��������� +#define ERR_RPT_NOT_EXIST 3 +#define ERR_NOT_ENOUGH_BUF 4 + +#endif diff --git a/src/include/cJSON.h b/src/include/cJSON.h new file mode 100644 index 0000000..6e0bde9 --- /dev/null +++ b/src/include/cJSON.h @@ -0,0 +1,277 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#ifndef cJSON__h +#define cJSON__h + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* project version */ +#define CJSON_VERSION_MAJOR 1 +#define CJSON_VERSION_MINOR 7 +#define CJSON_VERSION_PATCH 7 + +#include <stddef.h> + +/* cJSON Types: */ +#define cJSON_Invalid (0) +#define cJSON_False (1 << 0) +#define cJSON_True (1 << 1) +#define cJSON_NULL (1 << 2) +#define cJSON_Number (1 << 3) +#define cJSON_String (1 << 4) +#define cJSON_Array (1 << 5) +#define cJSON_Object (1 << 6) +#define cJSON_Raw (1 << 7) /* raw json */ + +#define cJSON_IsReference 256 +#define cJSON_StringIsConst 512 + +/* The cJSON structure: */ +typedef struct cJSON +{ + /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ + struct cJSON *next; + struct cJSON *prev; + /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ + struct cJSON *child; + + /* The type of the item, as above. */ + int type; + + /* The item's string, if type==cJSON_String and type == cJSON_Raw */ + char *valuestring; + /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */ + int valueint; + /* The item's number, if type==cJSON_Number */ + double valuedouble; + + /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ + char *string; +} cJSON; + +typedef struct cJSON_Hooks +{ + void *(*malloc_fn)(size_t sz); + void (*free_fn)(void *ptr); +} cJSON_Hooks; + +typedef int cJSON_bool; + +#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)) +#define __WINDOWS__ +#endif +#ifdef __WINDOWS__ + +/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 2 define options: + +CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols +CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default) +CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol + +For *nix builds that support visibility attribute, you can define similar behavior by + +setting default visibility to hidden by adding +-fvisibility=hidden (for gcc) +or +-xldscope=hidden (for sun cc) +to CFLAGS + +then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does + +*/ + +/* export symbols by default, this is necessary for copy pasting the C and header file */ +#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS) +#define CJSON_EXPORT_SYMBOLS +#endif + +#if defined(CJSON_HIDE_SYMBOLS) +#define CJSON_PUBLIC(type) type __stdcall +#elif defined(CJSON_EXPORT_SYMBOLS) +#define CJSON_PUBLIC(type) __declspec(dllexport) type __stdcall +#elif defined(CJSON_IMPORT_SYMBOLS) +#define CJSON_PUBLIC(type) __declspec(dllimport) type __stdcall +#endif +#else /* !WIN32 */ +#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY) +#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type +#else +#define CJSON_PUBLIC(type) type +#endif +#endif + +/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them. + * This is to prevent stack overflows. */ +#ifndef CJSON_NESTING_LIMIT +#define CJSON_NESTING_LIMIT 1000 +#endif + +/* returns the version of cJSON as a string */ +CJSON_PUBLIC(const char*) cJSON_Version(void); + +/* Supply malloc, realloc and free functions to cJSON */ +CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks); + +/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */ +/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */ +CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); +/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ +/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */ +CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated); + +/* Render a cJSON entity to text for transfer/storage. */ +CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item); +/* Render a cJSON entity to text for transfer/storage without any formatting. */ +CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item); +/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ +CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt); +/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */ +/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */ +CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format); +/* Delete a cJSON entity and all subentities. */ +CJSON_PUBLIC(void) cJSON_Delete(cJSON *c); + +/* Returns the number of items in an array (or object). */ +CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array); +/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */ +CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index); +/* Get item "string" from object. Case insensitive. */ +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string); +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string); +CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string); +/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ +CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void); + +/* Check if the item is a string and return its valuestring */ +CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item); + +/* These functions check the type of an item */ +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item); + +/* These calls create a cJSON item of the appropriate type. */ +CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean); +CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num); +CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string); +/* raw json */ +CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw); +CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); + +/* Create a string where valuestring references a string so + * it will not be freed by cJSON_Delete */ +CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string); +/* Create an object/arrray that only references it's elements so + * they will not be freed by cJSON_Delete */ +CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child); +CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child); + +/* These utilities create an Array of count items. */ +CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count); + +/* Append item to the specified array/object. */ +CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item); +CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); +/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object. + * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before + * writing to `item->string` */ +CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item); +/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ +CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); +CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); + +/* Remove/Detatch items from Arrays/Objects. */ +CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which); +CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string); +CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string); +CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string); + +/* Update array items. */ +CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */ +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement); +CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); +CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); +CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem); + +/* Duplicate a cJSON item */ +CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse); +/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will +need to be released. With recurse!=0, it will duplicate any children connected to the item. +The item->next and ->prev pointers are always zero on return from Duplicate. */ +/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal. + * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */ +CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive); + + +CJSON_PUBLIC(void) cJSON_Minify(char *json); + +/* Helper functions for creating and adding items to an object at the same time. + * They return the added item or NULL on failure. */ +CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean); +CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number); +CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string); +CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw); +CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name); + +/* When assigning an integer value, it needs to be propagated to valuedouble too. */ +#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number)) +/* helper for the cJSON_SetNumberValue macro */ +CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number); +#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number)) + +/* Macro for iterating over an array or object */ +#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next) + +/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */ +CJSON_PUBLIC(void *) cJSON_malloc(size_t size); +CJSON_PUBLIC(void) cJSON_free(void *object); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/include/cache_evbase_client.h b/src/include/cache_evbase_client.h new file mode 100644 index 0000000..feab191 --- /dev/null +++ b/src/include/cache_evbase_client.h @@ -0,0 +1,69 @@ +#ifndef __CACHE_ASYN_CLIENT_H__ +#define __CACHE_ASYN_CLIENT_H__ + +#include <event2/event.h> +#include <event.h> + +#include "tango_cache_client.h" + +/* API��ʹ��˵���ο�tango_cache_client.h */ + +struct cache_evbase_instance +{ + struct tango_cache_instance *instance; + evutil_socket_t notify_readfd; + evutil_socket_t notify_sendfd; + struct event_base* evbase; +}; + +struct cache_evbase_ctx +{ + size_t object_size; //tango_ctx�������Ա�����ع�����ֱ�ӻ�ȡ�Ļ����ڶ�дһ�������� + struct tango_cache_ctx *ctx; + struct tango_losf_meta *losf_meta; //LOSFһ�����ϴ�ʱû��ctx + struct cache_evbase_instance *instance_asyn; +}; + +/*����API�̰߳�ȫ������ͬһ��cache_evbase_ctx�����Կ��̷߳��ʡ�*/ + +enum CACHE_ERR_CODE cache_evbase_get_last_error(const struct cache_evbase_ctx *ctx_asyn); +enum CACHE_ERR_CODE cache_evbase_ctx_error(const struct cache_evbase_instance *instance); +long long cache_evbase_maximum_session(const struct cache_evbase_instance *instance); +void cache_evbase_get_statistics(const struct cache_evbase_instance *instance, struct cache_statistics *out); + +void cache_evbase_global_init(void); + +//ÿ��minio��Ⱥ��bucket����һ��parameter�����instance�ɹ���һ��parameter�� +struct tango_cache_parameter *cache_evbase_parameter_new(const char* profile_path, const char* section, void *runtimelog); + +/*����ʵ�����̰߳�ȫ���ڲ�������һ���߳�*/ +struct cache_evbase_instance *cache_evbase_instance_new(struct tango_cache_parameter *param, void *runtimelog); + +/******************************************* GET�ӿ� ****************************************/ +//�ɹ�����0��ʧ�ܷ���-1��future�ص���������������߳���ִ�У���ͬ +int cache_evbase_fetch_object(struct cache_evbase_instance *instance, struct future* f, struct tango_cache_meta_get *meta, enum OBJECT_LOCATION where_to_get); +int cache_evbase_head_object(struct cache_evbase_instance *instance, struct future* f, struct tango_cache_meta_get *meta); +struct tango_cache_result *cache_evbase_read_result(void *promise_result); + +/****************************************** DELETE�ӿ� **************************************/ +int cache_evbase_delete_object(struct cache_evbase_instance *instance, struct future* f, const char *objkey, const char *minio_addr=NULL, const char *bucket=NULL); + +/***************************************** һ�����ϴ��ӿ� **********************************/ +int cache_evbase_upload_once_data(struct cache_evbase_instance *instance, struct future* f, + enum PUT_MEMORY_COPY_WAY way, const char *data, size_t size, + struct tango_cache_meta_put *meta, + char *path/*OUT*/, size_t pathsize); +int cache_evbase_upload_once_evbuf(struct cache_evbase_instance *instance, struct future* f, + struct evbuffer *evbuf, + struct tango_cache_meta_put *meta, + char *path/*OUT*/, size_t pathsize); + +/****************************************** ��ʽ�ϴ��ӿ� ***********************************/ +struct cache_evbase_ctx *cache_evbase_update_start(struct cache_evbase_instance *instance, struct future* f, struct tango_cache_meta_put *meta); +int cache_evbase_update_frag_data(struct cache_evbase_ctx *ctx_asyn, enum PUT_MEMORY_COPY_WAY way, const char *data, size_t size); +int cache_evbase_update_frag_evbuf(struct cache_evbase_ctx *ctx_asyn, struct evbuffer *evbuf); +int cache_evbase_update_end(struct cache_evbase_ctx *ctx_asyn, char *path/*OUT*/, size_t pathsize); +void cache_evbase_update_cancel(struct cache_evbase_ctx *ctx_asyn); + +#endif + diff --git a/src/include/evdns.h b/src/include/evdns.h new file mode 100644 index 0000000..8672db0 --- /dev/null +++ b/src/include/evdns.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2000-2007 Niels Provos <[email protected]> + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EVENT1_EVDNS_H_INCLUDED_ +#define EVENT1_EVDNS_H_INCLUDED_ + +/** @file evdns.h + + A dns subsystem for Libevent. + + The <evdns.h> header is deprecated in Libevent 2.0 and later; please + use <event2/evdns.h> instead. Depending on what functionality you + need, you may also want to include more of the other <event2/...> + headers. + */ + +#include <event.h> +#include <event2/dns.h> +#include <event2/dns_compat.h> +#include <event2/dns_struct.h> + +#endif /* EVENT1_EVDNS_H_INCLUDED_ */ diff --git a/src/include/event.h b/src/include/event.h new file mode 100644 index 0000000..ba51867 --- /dev/null +++ b/src/include/event.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2000-2007 Niels Provos <[email protected]> + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EVENT1_EVENT_H_INCLUDED_ +#define EVENT1_EVENT_H_INCLUDED_ + +/** @file event.h + + A library for writing event-driven network servers. + + The <event.h> header is deprecated in Libevent 2.0 and later; please + use <event2/event.h> instead. Depending on what functionality you + need, you may also want to include more of the other event2/ + headers. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <event2/event-config.h> +#ifdef EVENT__HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef EVENT__HAVE_SYS_TIME_H +#include <sys/time.h> +#endif +#ifdef EVENT__HAVE_STDINT_H +#include <stdint.h> +#endif +#include <stdarg.h> + +/* For int types. */ +#include <evutil.h> + +#ifdef _WIN32 +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include <winsock2.h> +#include <windows.h> +#undef WIN32_LEAN_AND_MEAN +#endif + +#include <event2/event_struct.h> +#include <event2/event.h> +#include <event2/event_compat.h> +#include <event2/buffer.h> +#include <event2/buffer_compat.h> +#include <event2/bufferevent.h> +#include <event2/bufferevent_struct.h> +#include <event2/bufferevent_compat.h> +#include <event2/tag.h> +#include <event2/tag_compat.h> + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT1_EVENT_H_INCLUDED_ */ diff --git a/src/include/event2/buffer.h b/src/include/event2/buffer.h new file mode 100644 index 0000000..468588b --- /dev/null +++ b/src/include/event2/buffer.h @@ -0,0 +1,1076 @@ +/* + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EVENT2_BUFFER_H_INCLUDED_ +#define EVENT2_BUFFER_H_INCLUDED_ + +/** @file event2/buffer.h + + Functions for buffering data for network sending or receiving. + + An evbuffer can be used for preparing data before sending it to + the network or conversely for reading data from the network. + Evbuffers try to avoid memory copies as much as possible. As a + result, evbuffers can be used to pass data around without actually + incurring the overhead of copying the data. + + A new evbuffer can be allocated with evbuffer_new(), and can be + freed with evbuffer_free(). Most users will be using evbuffers via + the bufferevent interface. To access a bufferevent's evbuffers, use + bufferevent_get_input() and bufferevent_get_output(). + + There are several guidelines for using evbuffers. + + - if you already know how much data you are going to add as a result + of calling evbuffer_add() multiple times, it makes sense to use + evbuffer_expand() first to make sure that enough memory is allocated + before hand. + + - evbuffer_add_buffer() adds the contents of one buffer to the other + without incurring any unnecessary memory copies. + + - evbuffer_add() and evbuffer_add_buffer() do not mix very well: + if you use them, you will wind up with fragmented memory in your + buffer. + + - For high-performance code, you may want to avoid copying data into and out + of buffers. You can skip the copy step by using + evbuffer_reserve_space()/evbuffer_commit_space() when writing into a + buffer, and evbuffer_peek() when reading. + + In Libevent 2.0 and later, evbuffers are represented using a linked + list of memory chunks, with pointers to the first and last chunk in + the chain. + + As the contents of an evbuffer can be stored in multiple different + memory blocks, it cannot be accessed directly. Instead, evbuffer_pullup() + can be used to force a specified number of bytes to be contiguous. This + will cause memory reallocation and memory copies if the data is split + across multiple blocks. It is more efficient, however, to use + evbuffer_peek() if you don't require that the memory to be contiguous. + */ + +#include <event2/visibility.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#include <event2/event-config.h> +#include <stdarg.h> +#ifdef EVENT__HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef EVENT__HAVE_SYS_UIO_H +#include <sys/uio.h> +#endif +#include <event2/util.h> + +/** + An evbuffer is an opaque data type for efficiently buffering data to be + sent or received on the network. + + @see event2/event.h for more information +*/ +struct evbuffer +#ifdef EVENT_IN_DOXYGEN_ +{} +#endif +; + +/** + Pointer to a position within an evbuffer. + + Used when repeatedly searching through a buffer. Calling any function + that modifies or re-packs the buffer contents may invalidate all + evbuffer_ptrs for that buffer. Do not modify or contruct these values + except with evbuffer_ptr_set. + + An evbuffer_ptr can represent any position from the start of a buffer up + to a position immediately after the end of a buffer. + + @see evbuffer_ptr_set() + */ +struct evbuffer_ptr { + ev_ssize_t pos; + + /* Do not alter or rely on the values of fields: they are for internal + * use */ + struct { + void *chain; + size_t pos_in_chain; + } internal_; +}; + +/** Describes a single extent of memory inside an evbuffer. Used for + direct-access functions. + + @see evbuffer_reserve_space, evbuffer_commit_space, evbuffer_peek + */ +#ifdef EVENT__HAVE_SYS_UIO_H +#define evbuffer_iovec iovec +/* Internal use -- defined only if we are using the native struct iovec */ +#define EVBUFFER_IOVEC_IS_NATIVE_ +#else +struct evbuffer_iovec { + /** The start of the extent of memory. */ + void *iov_base; + /** The length of the extent of memory. */ + size_t iov_len; +}; +#endif + +/** + Allocate storage for a new evbuffer. + + @return a pointer to a newly allocated evbuffer struct, or NULL if an error + occurred + */ +EVENT2_EXPORT_SYMBOL +struct evbuffer *evbuffer_new(void); +/** + Deallocate storage for an evbuffer. + + @param buf pointer to the evbuffer to be freed + */ +EVENT2_EXPORT_SYMBOL +void evbuffer_free(struct evbuffer *buf); + +/** + Enable locking on an evbuffer so that it can safely be used by multiple + threads at the same time. + + NOTE: when locking is enabled, the lock will be held when callbacks are + invoked. This could result in deadlock if you aren't careful. Plan + accordingly! + + @param buf An evbuffer to make lockable. + @param lock A lock object, or NULL if we should allocate our own. + @return 0 on success, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_enable_locking(struct evbuffer *buf, void *lock); + +/** + Acquire the lock on an evbuffer. Has no effect if locking was not enabled + with evbuffer_enable_locking. +*/ +EVENT2_EXPORT_SYMBOL +void evbuffer_lock(struct evbuffer *buf); + +/** + Release the lock on an evbuffer. Has no effect if locking was not enabled + with evbuffer_enable_locking. +*/ +EVENT2_EXPORT_SYMBOL +void evbuffer_unlock(struct evbuffer *buf); + + +/** If this flag is set, then we will not use evbuffer_peek(), + * evbuffer_remove(), evbuffer_remove_buffer(), and so on to read bytes + * from this buffer: we'll only take bytes out of this buffer by + * writing them to the network (as with evbuffer_write_atmost), by + * removing them without observing them (as with evbuffer_drain), + * or by copying them all out at once (as with evbuffer_add_buffer). + * + * Using this option allows the implementation to use sendfile-based + * operations for evbuffer_add_file(); see that function for more + * information. + * + * This flag is on by default for bufferevents that can take advantage + * of it; you should never actually need to set it on a bufferevent's + * output buffer. + */ +#define EVBUFFER_FLAG_DRAINS_TO_FD 1 + +/** Change the flags that are set for an evbuffer by adding more. + * + * @param buffer the evbuffer that the callback is watching. + * @param cb the callback whose status we want to change. + * @param flags One or more EVBUFFER_FLAG_* options + * @return 0 on success, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_set_flags(struct evbuffer *buf, ev_uint64_t flags); +/** Change the flags that are set for an evbuffer by removing some. + * + * @param buffer the evbuffer that the callback is watching. + * @param cb the callback whose status we want to change. + * @param flags One or more EVBUFFER_FLAG_* options + * @return 0 on success, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_clear_flags(struct evbuffer *buf, ev_uint64_t flags); + +/** + Returns the total number of bytes stored in the evbuffer + + @param buf pointer to the evbuffer + @return the number of bytes stored in the evbuffer +*/ +EVENT2_EXPORT_SYMBOL +size_t evbuffer_get_length(const struct evbuffer *buf); + +/** + Returns the number of contiguous available bytes in the first buffer chain. + + This is useful when processing data that might be split into multiple + chains, or that might all be in the first chain. Calls to + evbuffer_pullup() that cause reallocation and copying of data can thus be + avoided. + + @param buf pointer to the evbuffer + @return 0 if no data is available, otherwise the number of available bytes + in the first buffer chain. +*/ +EVENT2_EXPORT_SYMBOL +size_t evbuffer_get_contiguous_space(const struct evbuffer *buf); + +/** + Expands the available space in an evbuffer. + + Expands the available space in the evbuffer to at least datlen, so that + appending datlen additional bytes will not require any new allocations. + + @param buf the evbuffer to be expanded + @param datlen the new minimum length requirement + @return 0 if successful, or -1 if an error occurred +*/ +EVENT2_EXPORT_SYMBOL +int evbuffer_expand(struct evbuffer *buf, size_t datlen); + +/** + Reserves space in the last chain or chains of an evbuffer. + + Makes space available in the last chain or chains of an evbuffer that can + be arbitrarily written to by a user. The space does not become + available for reading until it has been committed with + evbuffer_commit_space(). + + The space is made available as one or more extents, represented by + an initial pointer and a length. You can force the memory to be + available as only one extent. Allowing more extents, however, makes the + function more efficient. + + Multiple subsequent calls to this function will make the same space + available until evbuffer_commit_space() has been called. + + It is an error to do anything that moves around the buffer's internal + memory structures before committing the space. + + NOTE: The code currently does not ever use more than two extents. + This may change in future versions. + + @param buf the evbuffer in which to reserve space. + @param size how much space to make available, at minimum. The + total length of the extents may be greater than the requested + length. + @param vec an array of one or more evbuffer_iovec structures to + hold pointers to the reserved extents of memory. + @param n_vec The length of the vec array. Must be at least 1; + 2 is more efficient. + @return the number of provided extents, or -1 on error. + @see evbuffer_commit_space() +*/ +EVENT2_EXPORT_SYMBOL +int +evbuffer_reserve_space(struct evbuffer *buf, ev_ssize_t size, + struct evbuffer_iovec *vec, int n_vec); + +/** + Commits previously reserved space. + + Commits some of the space previously reserved with + evbuffer_reserve_space(). It then becomes available for reading. + + This function may return an error if the pointer in the extents do + not match those returned from evbuffer_reserve_space, or if data + has been added to the buffer since the space was reserved. + + If you want to commit less data than you got reserved space for, + modify the iov_len pointer of the appropriate extent to a smaller + value. Note that you may have received more space than you + requested if it was available! + + @param buf the evbuffer in which to reserve space. + @param vec one or two extents returned by evbuffer_reserve_space. + @param n_vecs the number of extents. + @return 0 on success, -1 on error + @see evbuffer_reserve_space() +*/ +EVENT2_EXPORT_SYMBOL +int evbuffer_commit_space(struct evbuffer *buf, + struct evbuffer_iovec *vec, int n_vecs); + +/** + Append data to the end of an evbuffer. + + @param buf the evbuffer to be appended to + @param data pointer to the beginning of the data buffer + @param datlen the number of bytes to be copied from the data buffer + @return 0 on success, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_add(struct evbuffer *buf, const void *data, size_t datlen); + + +/** + Read data from an evbuffer and drain the bytes read. + + If more bytes are requested than are available in the evbuffer, we + only extract as many bytes as were available. + + @param buf the evbuffer to be read from + @param data the destination buffer to store the result + @param datlen the maximum size of the destination buffer + @return the number of bytes read, or -1 if we can't drain the buffer. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen); + +/** + Read data from an evbuffer, and leave the buffer unchanged. + + If more bytes are requested than are available in the evbuffer, we + only extract as many bytes as were available. + + @param buf the evbuffer to be read from + @param data_out the destination buffer to store the result + @param datlen the maximum size of the destination buffer + @return the number of bytes read, or -1 if we can't drain the buffer. + */ +EVENT2_EXPORT_SYMBOL +ev_ssize_t evbuffer_copyout(struct evbuffer *buf, void *data_out, size_t datlen); + +/** + Read data from the middle of an evbuffer, and leave the buffer unchanged. + + If more bytes are requested than are available in the evbuffer, we + only extract as many bytes as were available. + + @param buf the evbuffer to be read from + @param pos the position to start reading from + @param data_out the destination buffer to store the result + @param datlen the maximum size of the destination buffer + @return the number of bytes read, or -1 if we can't drain the buffer. + */ +EVENT2_EXPORT_SYMBOL +ev_ssize_t evbuffer_copyout_from(struct evbuffer *buf, const struct evbuffer_ptr *pos, void *data_out, size_t datlen); + +/** + Read data from an evbuffer into another evbuffer, draining + the bytes from the source buffer. This function avoids copy + operations to the extent possible. + + If more bytes are requested than are available in src, the src + buffer is drained completely. + + @param src the evbuffer to be read from + @param dst the destination evbuffer to store the result into + @param datlen the maximum numbers of bytes to transfer + @return the number of bytes read + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_remove_buffer(struct evbuffer *src, struct evbuffer *dst, + size_t datlen); + +/** Used to tell evbuffer_readln what kind of line-ending to look for. + */ +enum evbuffer_eol_style { + /** Any sequence of CR and LF characters is acceptable as an + * EOL. + * + * Note that this style can produce ambiguous results: the + * sequence "CRLF" will be treated as a single EOL if it is + * all in the buffer at once, but if you first read a CR from + * the network and later read an LF from the network, it will + * be treated as two EOLs. + */ + EVBUFFER_EOL_ANY, + /** An EOL is an LF, optionally preceded by a CR. This style is + * most useful for implementing text-based internet protocols. */ + EVBUFFER_EOL_CRLF, + /** An EOL is a CR followed by an LF. */ + EVBUFFER_EOL_CRLF_STRICT, + /** An EOL is a LF. */ + EVBUFFER_EOL_LF, + /** An EOL is a NUL character (that is, a single byte with value 0) */ + EVBUFFER_EOL_NUL +}; + +/** + * Read a single line from an evbuffer. + * + * Reads a line terminated by an EOL as determined by the evbuffer_eol_style + * argument. Returns a newly allocated nul-terminated string; the caller must + * free the returned value. The EOL is not included in the returned string. + * + * @param buffer the evbuffer to read from + * @param n_read_out if non-NULL, points to a size_t that is set to the + * number of characters in the returned string. This is useful for + * strings that can contain NUL characters. + * @param eol_style the style of line-ending to use. + * @return pointer to a single line, or NULL if an error occurred + */ +EVENT2_EXPORT_SYMBOL +char *evbuffer_readln(struct evbuffer *buffer, size_t *n_read_out, + enum evbuffer_eol_style eol_style); + +/** + Move all data from one evbuffer into another evbuffer. + + This is a destructive add. The data from one buffer moves into + the other buffer. However, no unnecessary memory copies occur. + + @param outbuf the output buffer + @param inbuf the input buffer + @return 0 if successful, or -1 if an error occurred + + @see evbuffer_remove_buffer() + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf); + +/** + Copy data from one evbuffer into another evbuffer. + + This is a non-destructive add. The data from one buffer is copied + into the other buffer. However, no unnecessary memory copies occur. + + Note that buffers already containing buffer references can't be added + to other buffers. + + @param outbuf the output buffer + @param inbuf the input buffer + @return 0 if successful, or -1 if an error occurred + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_add_buffer_reference(struct evbuffer *outbuf, + struct evbuffer *inbuf); + +/** + A cleanup function for a piece of memory added to an evbuffer by + reference. + + @see evbuffer_add_reference() + */ +typedef void (*evbuffer_ref_cleanup_cb)(const void *data, + size_t datalen, void *extra); + +/** + Reference memory into an evbuffer without copying. + + The memory needs to remain valid until all the added data has been + read. This function keeps just a reference to the memory without + actually incurring the overhead of a copy. + + @param outbuf the output buffer + @param data the memory to reference + @param datlen how memory to reference + @param cleanupfn callback to be invoked when the memory is no longer + referenced by this evbuffer. + @param cleanupfn_arg optional argument to the cleanup callback + @return 0 if successful, or -1 if an error occurred + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_add_reference(struct evbuffer *outbuf, + const void *data, size_t datlen, + evbuffer_ref_cleanup_cb cleanupfn, void *cleanupfn_arg); + +/** + Copy data from a file into the evbuffer for writing to a socket. + + This function avoids unnecessary data copies between userland and + kernel. If sendfile is available and the EVBUFFER_FLAG_DRAINS_TO_FD + flag is set, it uses those functions. Otherwise, it tries to use + mmap (or CreateFileMapping on Windows). + + The function owns the resulting file descriptor and will close it + when finished transferring data. + + The results of using evbuffer_remove() or evbuffer_pullup() on + evbuffers whose data was added using this function are undefined. + + For more fine-grained control, use evbuffer_add_file_segment. + + @param outbuf the output buffer + @param fd the file descriptor + @param offset the offset from which to read data + @param length how much data to read, or -1 to read as much as possible. + (-1 requires that 'fd' support fstat.) + @return 0 if successful, or -1 if an error occurred +*/ + +EVENT2_EXPORT_SYMBOL +int evbuffer_add_file(struct evbuffer *outbuf, int fd, ev_off_t offset, + ev_off_t length); + +/** + An evbuffer_file_segment holds a reference to a range of a file -- + possibly the whole file! -- for use in writing from an evbuffer to a + socket. It could be implemented with mmap, sendfile, splice, or (if all + else fails) by just pulling all the data into RAM. A single + evbuffer_file_segment can be added more than once, and to more than one + evbuffer. + */ +struct evbuffer_file_segment; + +/** + Flag for creating evbuffer_file_segment: If this flag is set, then when + the evbuffer_file_segment is freed and no longer in use by any + evbuffer, the underlying fd is closed. + */ +#define EVBUF_FS_CLOSE_ON_FREE 0x01 +/** + Flag for creating evbuffer_file_segment: Disable memory-map based + implementations. + */ +#define EVBUF_FS_DISABLE_MMAP 0x02 +/** + Flag for creating evbuffer_file_segment: Disable direct fd-to-fd + implementations (including sendfile and splice). + + You might want to use this option if data needs to be taken from the + evbuffer by any means other than writing it to the network: the sendfile + backend is fast, but it only works for sending files directly to the + network. + */ +#define EVBUF_FS_DISABLE_SENDFILE 0x04 +/** + Flag for creating evbuffer_file_segment: Do not allocate a lock for this + segment. If this option is set, then neither the segment nor any + evbuffer it is added to may ever be accessed from more than one thread + at a time. + */ +#define EVBUF_FS_DISABLE_LOCKING 0x08 + +/** + A cleanup function for a evbuffer_file_segment added to an evbuffer + for reference. + */ +typedef void (*evbuffer_file_segment_cleanup_cb)( + struct evbuffer_file_segment const* seg, int flags, void* arg); + +/** + Create and return a new evbuffer_file_segment for reading data from a + file and sending it out via an evbuffer. + + This function avoids unnecessary data copies between userland and + kernel. Where available, it uses sendfile or splice. + + The file descriptor must not be closed so long as any evbuffer is using + this segment. + + The results of using evbuffer_remove() or evbuffer_pullup() or any other + function that reads bytes from an evbuffer on any evbuffer containing + the newly returned segment are undefined, unless you pass the + EVBUF_FS_DISABLE_SENDFILE flag to this function. + + @param fd an open file to read from. + @param offset an index within the file at which to start reading + @param length how much data to read, or -1 to read as much as possible. + (-1 requires that 'fd' support fstat.) + @param flags any number of the EVBUF_FS_* flags + @return a new evbuffer_file_segment, or NULL on failure. + **/ +EVENT2_EXPORT_SYMBOL +struct evbuffer_file_segment *evbuffer_file_segment_new( + int fd, ev_off_t offset, ev_off_t length, unsigned flags); + +/** + Free an evbuffer_file_segment + + It is safe to call this function even if the segment has been added to + one or more evbuffers. The evbuffer_file_segment will not be freed + until no more references to it exist. + */ +EVENT2_EXPORT_SYMBOL +void evbuffer_file_segment_free(struct evbuffer_file_segment *seg); + +/** + Add cleanup callback and argument for the callback to an + evbuffer_file_segment. + + The cleanup callback will be invoked when no more references to the + evbuffer_file_segment exist. + **/ +EVENT2_EXPORT_SYMBOL +void evbuffer_file_segment_add_cleanup_cb(struct evbuffer_file_segment *seg, + evbuffer_file_segment_cleanup_cb cb, void* arg); + +/** + Insert some or all of an evbuffer_file_segment at the end of an evbuffer + + Note that the offset and length parameters of this function have a + different meaning from those provided to evbuffer_file_segment_new: When + you create the segment, the offset is the offset _within the file_, and + the length is the length _of the segment_, whereas when you add a + segment to an evbuffer, the offset is _within the segment_ and the + length is the length of the _part of the segment you want to use. + + In other words, if you have a 10 KiB file, and you create an + evbuffer_file_segment for it with offset 20 and length 1000, it will + refer to bytes 20..1019 inclusive. If you then pass this segment to + evbuffer_add_file_segment and specify an offset of 20 and a length of + 50, you will be adding bytes 40..99 inclusive. + + @param buf the evbuffer to append to + @param seg the segment to add + @param offset the offset within the segment to start from + @param length the amount of data to add, or -1 to add it all. + @return 0 on success, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_add_file_segment(struct evbuffer *buf, + struct evbuffer_file_segment *seg, ev_off_t offset, ev_off_t length); + +/** + Append a formatted string to the end of an evbuffer. + + The string is formated as printf. + + @param buf the evbuffer that will be appended to + @param fmt a format string + @param ... arguments that will be passed to printf(3) + @return The number of bytes added if successful, or -1 if an error occurred. + + @see evutil_printf(), evbuffer_add_vprintf() + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_add_printf(struct evbuffer *buf, const char *fmt, ...) +#ifdef __GNUC__ + __attribute__((format(printf, 2, 3))) +#endif +; + +/** + Append a va_list formatted string to the end of an evbuffer. + + @param buf the evbuffer that will be appended to + @param fmt a format string + @param ap a varargs va_list argument array that will be passed to vprintf(3) + @return The number of bytes added if successful, or -1 if an error occurred. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap) +#ifdef __GNUC__ + __attribute__((format(printf, 2, 0))) +#endif +; + + +/** + Remove a specified number of bytes data from the beginning of an evbuffer. + + @param buf the evbuffer to be drained + @param len the number of bytes to drain from the beginning of the buffer + @return 0 on success, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_drain(struct evbuffer *buf, size_t len); + + +/** + Write the contents of an evbuffer to a file descriptor. + + The evbuffer will be drained after the bytes have been successfully written. + + @param buffer the evbuffer to be written and drained + @param fd the file descriptor to be written to + @return the number of bytes written, or -1 if an error occurred + @see evbuffer_read() + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_write(struct evbuffer *buffer, evutil_socket_t fd); + +/** + Write some of the contents of an evbuffer to a file descriptor. + + The evbuffer will be drained after the bytes have been successfully written. + + @param buffer the evbuffer to be written and drained + @param fd the file descriptor to be written to + @param howmuch the largest allowable number of bytes to write, or -1 + to write as many bytes as we can. + @return the number of bytes written, or -1 if an error occurred + @see evbuffer_read() + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_write_atmost(struct evbuffer *buffer, evutil_socket_t fd, + ev_ssize_t howmuch); + +/** + Read from a file descriptor and store the result in an evbuffer. + + @param buffer the evbuffer to store the result + @param fd the file descriptor to read from + @param howmuch the number of bytes to be read + @return the number of bytes read, or -1 if an error occurred + @see evbuffer_write() + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_read(struct evbuffer *buffer, evutil_socket_t fd, int howmuch); + +/** + Search for a string within an evbuffer. + + @param buffer the evbuffer to be searched + @param what the string to be searched for + @param len the length of the search string + @param start NULL or a pointer to a valid struct evbuffer_ptr. + @return a struct evbuffer_ptr whose 'pos' field has the offset of the + first occurrence of the string in the buffer after 'start'. The 'pos' + field of the result is -1 if the string was not found. + */ +EVENT2_EXPORT_SYMBOL +struct evbuffer_ptr evbuffer_search(struct evbuffer *buffer, const char *what, size_t len, const struct evbuffer_ptr *start); + +/** + Search for a string within part of an evbuffer. + + @param buffer the evbuffer to be searched + @param what the string to be searched for + @param len the length of the search string + @param start NULL or a pointer to a valid struct evbuffer_ptr that + indicates where we should start searching. + @param end NULL or a pointer to a valid struct evbuffer_ptr that + indicates where we should stop searching. + @return a struct evbuffer_ptr whose 'pos' field has the offset of the + first occurrence of the string in the buffer after 'start'. The 'pos' + field of the result is -1 if the string was not found. + */ +EVENT2_EXPORT_SYMBOL +struct evbuffer_ptr evbuffer_search_range(struct evbuffer *buffer, const char *what, size_t len, const struct evbuffer_ptr *start, const struct evbuffer_ptr *end); + +/** + Defines how to adjust an evbuffer_ptr by evbuffer_ptr_set() + + @see evbuffer_ptr_set() */ +enum evbuffer_ptr_how { + /** Sets the pointer to the position; can be called on with an + uninitialized evbuffer_ptr. */ + EVBUFFER_PTR_SET, + /** Advances the pointer by adding to the current position. */ + EVBUFFER_PTR_ADD +}; + +/** + Sets the search pointer in the buffer to position. + + There are two ways to use this function: you can call + evbuffer_ptr_set(buf, &pos, N, EVBUFFER_PTR_SET) + to move 'pos' to a position 'N' bytes after the start of the buffer, or + evbuffer_ptr_set(buf, &pos, N, EVBUFFER_PTR_ADD) + to move 'pos' forward by 'N' bytes. + + If evbuffer_ptr is not initialized, this function can only be called + with EVBUFFER_PTR_SET. + + An evbuffer_ptr can represent any position from the start of the buffer to + a position immediately after the end of the buffer. + + @param buffer the evbuffer to be search + @param ptr a pointer to a struct evbuffer_ptr + @param position the position at which to start the next search + @param how determines how the pointer should be manipulated. + @returns 0 on success or -1 otherwise +*/ +EVENT2_EXPORT_SYMBOL +int +evbuffer_ptr_set(struct evbuffer *buffer, struct evbuffer_ptr *ptr, + size_t position, enum evbuffer_ptr_how how); + +/** + Search for an end-of-line string within an evbuffer. + + @param buffer the evbuffer to be searched + @param start NULL or a pointer to a valid struct evbuffer_ptr to start + searching at. + @param eol_len_out If non-NULL, the pointed-to value will be set to + the length of the end-of-line string. + @param eol_style The kind of EOL to look for; see evbuffer_readln() for + more information + @return a struct evbuffer_ptr whose 'pos' field has the offset of the + first occurrence EOL in the buffer after 'start'. The 'pos' + field of the result is -1 if the string was not found. + */ +EVENT2_EXPORT_SYMBOL +struct evbuffer_ptr evbuffer_search_eol(struct evbuffer *buffer, + struct evbuffer_ptr *start, size_t *eol_len_out, + enum evbuffer_eol_style eol_style); + +/** Function to peek at data inside an evbuffer without removing it or + copying it out. + + Pointers to the data are returned by filling the 'vec_out' array + with pointers to one or more extents of data inside the buffer. + + The total data in the extents that you get back may be more than + you requested (if there is more data last extent than you asked + for), or less (if you do not provide enough evbuffer_iovecs, or if + the buffer does not have as much data as you asked to see). + + @param buffer the evbuffer to peek into, + @param len the number of bytes to try to peek. If len is negative, we + will try to fill as much of vec_out as we can. If len is negative + and vec_out is not provided, we return the number of evbuffer_iovecs + that would be needed to get all the data in the buffer. + @param start_at an evbuffer_ptr indicating the point at which we + should start looking for data. NULL means, "At the start of the + buffer." + @param vec_out an array of evbuffer_iovec + @param n_vec the length of vec_out. If 0, we only count how many + extents would be necessary to point to the requested amount of + data. + @return The number of extents needed. This may be less than n_vec + if we didn't need all the evbuffer_iovecs we were given, or more + than n_vec if we would need more to return all the data that was + requested. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_peek(struct evbuffer *buffer, ev_ssize_t len, + struct evbuffer_ptr *start_at, + struct evbuffer_iovec *vec_out, int n_vec); + + +/** Structure passed to an evbuffer_cb_func evbuffer callback + + @see evbuffer_cb_func, evbuffer_add_cb() + */ +struct evbuffer_cb_info { + /** The number of bytes in this evbuffer when callbacks were last + * invoked. */ + size_t orig_size; + /** The number of bytes added since callbacks were last invoked. */ + size_t n_added; + /** The number of bytes removed since callbacks were last invoked. */ + size_t n_deleted; +}; + +/** Type definition for a callback that is invoked whenever data is added or + removed from an evbuffer. + + An evbuffer may have one or more callbacks set at a time. The order + in which they are executed is undefined. + + A callback function may add more callbacks, or remove itself from the + list of callbacks, or add or remove data from the buffer. It may not + remove another callback from the list. + + If a callback adds or removes data from the buffer or from another + buffer, this can cause a recursive invocation of your callback or + other callbacks. If you ask for an infinite loop, you might just get + one: watch out! + + @param buffer the buffer whose size has changed + @param info a structure describing how the buffer changed. + @param arg a pointer to user data +*/ +typedef void (*evbuffer_cb_func)(struct evbuffer *buffer, const struct evbuffer_cb_info *info, void *arg); + +struct evbuffer_cb_entry; +/** Add a new callback to an evbuffer. + + Subsequent calls to evbuffer_add_cb() add new callbacks. To remove this + callback, call evbuffer_remove_cb or evbuffer_remove_cb_entry. + + @param buffer the evbuffer to be monitored + @param cb the callback function to invoke when the evbuffer is modified, + or NULL to remove all callbacks. + @param cbarg an argument to be provided to the callback function + @return a handle to the callback on success, or NULL on failure. + */ +EVENT2_EXPORT_SYMBOL +struct evbuffer_cb_entry *evbuffer_add_cb(struct evbuffer *buffer, evbuffer_cb_func cb, void *cbarg); + +/** Remove a callback from an evbuffer, given a handle returned from + evbuffer_add_cb. + + Calling this function invalidates the handle. + + @return 0 if a callback was removed, or -1 if no matching callback was + found. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_remove_cb_entry(struct evbuffer *buffer, + struct evbuffer_cb_entry *ent); + +/** Remove a callback from an evbuffer, given the function and argument + used to add it. + + @return 0 if a callback was removed, or -1 if no matching callback was + found. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_remove_cb(struct evbuffer *buffer, evbuffer_cb_func cb, void *cbarg); + +/** If this flag is not set, then a callback is temporarily disabled, and + * should not be invoked. + * + * @see evbuffer_cb_set_flags(), evbuffer_cb_clear_flags() + */ +#define EVBUFFER_CB_ENABLED 1 + +/** Change the flags that are set for a callback on a buffer by adding more. + + @param buffer the evbuffer that the callback is watching. + @param cb the callback whose status we want to change. + @param flags EVBUFFER_CB_ENABLED to re-enable the callback. + @return 0 on success, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_cb_set_flags(struct evbuffer *buffer, + struct evbuffer_cb_entry *cb, ev_uint32_t flags); + +/** Change the flags that are set for a callback on a buffer by removing some + + @param buffer the evbuffer that the callback is watching. + @param cb the callback whose status we want to change. + @param flags EVBUFFER_CB_ENABLED to disable the callback. + @return 0 on success, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_cb_clear_flags(struct evbuffer *buffer, + struct evbuffer_cb_entry *cb, ev_uint32_t flags); + +#if 0 +/** Postpone calling a given callback until unsuspend is called later. + + This is different from disabling the callback, since the callback will get + invoked later if the buffer size changes between now and when we unsuspend + it. + + @param the buffer that the callback is watching. + @param cb the callback we want to suspend. + */ +EVENT2_EXPORT_SYMBOL +void evbuffer_cb_suspend(struct evbuffer *buffer, struct evbuffer_cb_entry *cb); +/** Stop postponing a callback that we postponed with evbuffer_cb_suspend. + + If data was added to or removed from the buffer while the callback was + suspended, the callback will get called once now. + + @param the buffer that the callback is watching. + @param cb the callback we want to stop suspending. + */ +EVENT2_EXPORT_SYMBOL +void evbuffer_cb_unsuspend(struct evbuffer *buffer, struct evbuffer_cb_entry *cb); +#endif + +/** + Makes the data at the beginning of an evbuffer contiguous. + + @param buf the evbuffer to make contiguous + @param size the number of bytes to make contiguous, or -1 to make the + entire buffer contiguous. + @return a pointer to the contiguous memory array, or NULL if param size + requested more data than is present in the buffer. +*/ + +EVENT2_EXPORT_SYMBOL +unsigned char *evbuffer_pullup(struct evbuffer *buf, ev_ssize_t size); + +/** + Prepends data to the beginning of the evbuffer + + @param buf the evbuffer to which to prepend data + @param data a pointer to the memory to prepend + @param size the number of bytes to prepend + @return 0 if successful, or -1 otherwise +*/ + +EVENT2_EXPORT_SYMBOL +int evbuffer_prepend(struct evbuffer *buf, const void *data, size_t size); + +/** + Prepends all data from the src evbuffer to the beginning of the dst + evbuffer. + + @param dst the evbuffer to which to prepend data + @param src the evbuffer to prepend; it will be emptied as a result + @return 0 if successful, or -1 otherwise +*/ +EVENT2_EXPORT_SYMBOL +int evbuffer_prepend_buffer(struct evbuffer *dst, struct evbuffer* src); + +/** + Prevent calls that modify an evbuffer from succeeding. A buffer may + frozen at the front, at the back, or at both the front and the back. + + If the front of a buffer is frozen, operations that drain data from + the front of the buffer, or that prepend data to the buffer, will + fail until it is unfrozen. If the back a buffer is frozen, operations + that append data from the buffer will fail until it is unfrozen. + + @param buf The buffer to freeze + @param at_front If true, we freeze the front of the buffer. If false, + we freeze the back. + @return 0 on success, -1 on failure. +*/ +EVENT2_EXPORT_SYMBOL +int evbuffer_freeze(struct evbuffer *buf, int at_front); +/** + Re-enable calls that modify an evbuffer. + + @param buf The buffer to un-freeze + @param at_front If true, we unfreeze the front of the buffer. If false, + we unfreeze the back. + @return 0 on success, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_unfreeze(struct evbuffer *buf, int at_front); + +struct event_base; +/** + Force all the callbacks on an evbuffer to be run, not immediately after + the evbuffer is altered, but instead from inside the event loop. + + This can be used to serialize all the callbacks to a single thread + of execution. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_defer_callbacks(struct evbuffer *buffer, struct event_base *base); + +/** + Append data from 1 or more iovec's to an evbuffer + + Calculates the number of bytes needed for an iovec structure and guarantees + all data will fit into a single chain. Can be used in lieu of functionality + which calls evbuffer_add() constantly before being used to increase + performance. + + @param buffer the destination buffer + @param vec the source iovec + @param n_vec the number of iovec structures. + @return the number of bytes successfully written to the output buffer. +*/ +EVENT2_EXPORT_SYMBOL +size_t evbuffer_add_iovec(struct evbuffer * buffer, struct evbuffer_iovec * vec, int n_vec); + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_BUFFER_H_INCLUDED_ */ diff --git a/src/include/event2/buffer_compat.h b/src/include/event2/buffer_compat.h new file mode 100644 index 0000000..24f828c --- /dev/null +++ b/src/include/event2/buffer_compat.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef EVENT2_BUFFER_COMPAT_H_INCLUDED_ +#define EVENT2_BUFFER_COMPAT_H_INCLUDED_ + +#include <event2/visibility.h> + +/** @file event2/buffer_compat.h + + Obsolete and deprecated versions of the functions in buffer.h: provided + only for backward compatibility. + */ + + +/** + Obsolete alias for evbuffer_readln(buffer, NULL, EVBUFFER_EOL_ANY). + + @deprecated This function is deprecated because its behavior is not correct + for almost any protocol, and also because it's wholly subsumed by + evbuffer_readln(). + + @param buffer the evbuffer to read from + @return pointer to a single line, or NULL if an error occurred + +*/ +EVENT2_EXPORT_SYMBOL +char *evbuffer_readline(struct evbuffer *buffer); + +/** Type definition for a callback that is invoked whenever data is added or + removed from an evbuffer. + + An evbuffer may have one or more callbacks set at a time. The order + in which they are executed is undefined. + + A callback function may add more callbacks, or remove itself from the + list of callbacks, or add or remove data from the buffer. It may not + remove another callback from the list. + + If a callback adds or removes data from the buffer or from another + buffer, this can cause a recursive invocation of your callback or + other callbacks. If you ask for an infinite loop, you might just get + one: watch out! + + @param buffer the buffer whose size has changed + @param old_len the previous length of the buffer + @param new_len the current length of the buffer + @param arg a pointer to user data +*/ +typedef void (*evbuffer_cb)(struct evbuffer *buffer, size_t old_len, size_t new_len, void *arg); + +/** + Replace all callbacks on an evbuffer with a single new callback, or + remove them. + + Subsequent calls to evbuffer_setcb() replace callbacks set by previous + calls. Setting the callback to NULL removes any previously set callback. + + @deprecated This function is deprecated because it clears all previous + callbacks set on the evbuffer, which can cause confusing behavior if + multiple parts of the code all want to add their own callbacks on a + buffer. Instead, use evbuffer_add(), evbuffer_del(), and + evbuffer_setflags() to manage your own evbuffer callbacks without + interfering with callbacks set by others. + + @param buffer the evbuffer to be monitored + @param cb the callback function to invoke when the evbuffer is modified, + or NULL to remove all callbacks. + @param cbarg an argument to be provided to the callback function + */ +EVENT2_EXPORT_SYMBOL +void evbuffer_setcb(struct evbuffer *buffer, evbuffer_cb cb, void *cbarg); + + +/** + Find a string within an evbuffer. + + @param buffer the evbuffer to be searched + @param what the string to be searched for + @param len the length of the search string + @return a pointer to the beginning of the search string, or NULL if the search failed. + */ +EVENT2_EXPORT_SYMBOL +unsigned char *evbuffer_find(struct evbuffer *buffer, const unsigned char *what, size_t len); + +/** deprecated in favor of calling the functions directly */ +#define EVBUFFER_LENGTH(x) evbuffer_get_length(x) +/** deprecated in favor of calling the functions directly */ +#define EVBUFFER_DATA(x) evbuffer_pullup((x), -1) + +#endif + diff --git a/src/include/event2/bufferevent.h b/src/include/event2/bufferevent.h new file mode 100644 index 0000000..825918e --- /dev/null +++ b/src/include/event2/bufferevent.h @@ -0,0 +1,1021 @@ +/* + * Copyright (c) 2000-2007 Niels Provos <[email protected]> + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EVENT2_BUFFEREVENT_H_INCLUDED_ +#define EVENT2_BUFFEREVENT_H_INCLUDED_ + +/** + @file event2/bufferevent.h + + Functions for buffering data for network sending or receiving. Bufferevents + are higher level than evbuffers: each has an underlying evbuffer for reading + and one for writing, and callbacks that are invoked under certain + circumstances. + + A bufferevent provides input and output buffers that get filled and + drained automatically. The user of a bufferevent no longer deals + directly with the I/O, but instead is reading from input and writing + to output buffers. + + Once initialized, the bufferevent structure can be used repeatedly + with bufferevent_enable() and bufferevent_disable(). + + When reading is enabled, the bufferevent will try to read from the + file descriptor onto its input buffer, and call the read callback. + When writing is enabled, the bufferevent will try to write data onto its + file descriptor when the output buffer has enough data, and call the write + callback when the output buffer is sufficiently drained. + + Bufferevents come in several flavors, including: + + <dl> + <dt>Socket-based bufferevents</dt> + <dd>A bufferevent that reads and writes data onto a network + socket. Created with bufferevent_socket_new().</dd> + + <dt>Paired bufferevents</dt> + <dd>A pair of bufferevents that send and receive data to one + another without touching the network. Created with + bufferevent_pair_new().</dd> + + <dt>Filtering bufferevents</dt> + <dd>A bufferevent that transforms data, and sends or receives it + over another underlying bufferevent. Created with + bufferevent_filter_new().</dd> + + <dt>SSL-backed bufferevents</dt> + <dd>A bufferevent that uses the openssl library to send and + receive data over an encrypted connection. Created with + bufferevent_openssl_socket_new() or + bufferevent_openssl_filter_new().</dd> + </dl> + */ + +#include <event2/visibility.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#include <event2/event-config.h> +#ifdef EVENT__HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef EVENT__HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + +/* For int types. */ +#include <event2/util.h> + +/** @name Bufferevent event codes + + These flags are passed as arguments to a bufferevent's event callback. + + @{ +*/ +#define BEV_EVENT_READING 0x01 /**< error encountered while reading */ +#define BEV_EVENT_WRITING 0x02 /**< error encountered while writing */ +#define BEV_EVENT_EOF 0x10 /**< eof file reached */ +#define BEV_EVENT_ERROR 0x20 /**< unrecoverable error encountered */ +#define BEV_EVENT_TIMEOUT 0x40 /**< user-specified timeout reached */ +#define BEV_EVENT_CONNECTED 0x80 /**< connect operation finished. */ +/**@}*/ + +/** + An opaque type for handling buffered IO + + @see event2/bufferevent.h + */ +struct bufferevent +#ifdef EVENT_IN_DOXYGEN_ +{} +#endif +; +struct event_base; +struct evbuffer; +struct sockaddr; + +/** + A read or write callback for a bufferevent. + + The read callback is triggered when new data arrives in the input + buffer and the amount of readable data exceed the low watermark + which is 0 by default. + + The write callback is triggered if the write buffer has been + exhausted or fell below its low watermark. + + @param bev the bufferevent that triggered the callback + @param ctx the user-specified context for this bufferevent + */ +typedef void (*bufferevent_data_cb)(struct bufferevent *bev, void *ctx); + +/** + An event/error callback for a bufferevent. + + The event callback is triggered if either an EOF condition or another + unrecoverable error was encountered. + + For bufferevents with deferred callbacks, this is a bitwise OR of all errors + that have happened on the bufferevent since the last callback invocation. + + @param bev the bufferevent for which the error condition was reached + @param what a conjunction of flags: BEV_EVENT_READING or BEV_EVENT_WRITING + to indicate if the error was encountered on the read or write path, + and one of the following flags: BEV_EVENT_EOF, BEV_EVENT_ERROR, + BEV_EVENT_TIMEOUT, BEV_EVENT_CONNECTED. + + @param ctx the user-specified context for this bufferevent +*/ +typedef void (*bufferevent_event_cb)(struct bufferevent *bev, short what, void *ctx); + +/** Options that can be specified when creating a bufferevent */ +enum bufferevent_options { + /** If set, we close the underlying file + * descriptor/bufferevent/whatever when this bufferevent is freed. */ + BEV_OPT_CLOSE_ON_FREE = (1<<0), + + /** If set, and threading is enabled, operations on this bufferevent + * are protected by a lock */ + BEV_OPT_THREADSAFE = (1<<1), + + /** If set, callbacks are run deferred in the event loop. */ + BEV_OPT_DEFER_CALLBACKS = (1<<2), + + /** If set, callbacks are executed without locks being held on the + * bufferevent. This option currently requires that + * BEV_OPT_DEFER_CALLBACKS also be set; a future version of Libevent + * might remove the requirement.*/ + BEV_OPT_UNLOCK_CALLBACKS = (1<<3) +}; + +/** + Create a new socket bufferevent over an existing socket. + + @param base the event base to associate with the new bufferevent. + @param fd the file descriptor from which data is read and written to. + This file descriptor is not allowed to be a pipe(2). + It is safe to set the fd to -1, so long as you later + set it with bufferevent_setfd or bufferevent_socket_connect(). + @param options Zero or more BEV_OPT_* flags + @return a pointer to a newly allocated bufferevent struct, or NULL if an + error occurred + @see bufferevent_free() + */ +EVENT2_EXPORT_SYMBOL +struct bufferevent *bufferevent_socket_new(struct event_base *base, evutil_socket_t fd, int options); + +/** + Launch a connect() attempt with a socket-based bufferevent. + + When the connect succeeds, the eventcb will be invoked with + BEV_EVENT_CONNECTED set. + + If the bufferevent does not already have a socket set, we allocate a new + socket here and make it nonblocking before we begin. + + If no address is provided, we assume that the socket is already connecting, + and configure the bufferevent so that a BEV_EVENT_CONNECTED event will be + yielded when it is done connecting. + + @param bufev an existing bufferevent allocated with + bufferevent_socket_new(). + @param addr the address we should connect to + @param socklen The length of the address + @return 0 on success, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_socket_connect(struct bufferevent *, const struct sockaddr *, int); + +struct evdns_base; +/** + Resolve the hostname 'hostname' and connect to it as with + bufferevent_socket_connect(). + + @param bufev An existing bufferevent allocated with bufferevent_socket_new() + @param evdns_base Optionally, an evdns_base to use for resolving hostnames + asynchronously. May be set to NULL for a blocking resolve. + @param family A preferred address family to resolve addresses to, or + AF_UNSPEC for no preference. Only AF_INET, AF_INET6, and AF_UNSPEC are + supported. + @param hostname The hostname to resolve; see below for notes on recognized + formats + @param port The port to connect to on the resolved address. + @return 0 if successful, -1 on failure. + + Recognized hostname formats are: + + www.example.com (hostname) + 1.2.3.4 (ipv4address) + ::1 (ipv6address) + [::1] ([ipv6address]) + + Performance note: If you do not provide an evdns_base, this function + may block while it waits for a DNS response. This is probably not + what you want. + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_socket_connect_hostname(struct bufferevent *, + struct evdns_base *, int, const char *, int); + +/** + Return the error code for the last failed DNS lookup attempt made by + bufferevent_socket_connect_hostname(). + + @param bev The bufferevent object. + @return DNS error code. + @see evutil_gai_strerror() +*/ +EVENT2_EXPORT_SYMBOL +int bufferevent_socket_get_dns_error(struct bufferevent *bev); + +/** + Assign a bufferevent to a specific event_base. + + NOTE that only socket bufferevents support this function. + + @param base an event_base returned by event_init() + @param bufev a bufferevent struct returned by bufferevent_new() + or bufferevent_socket_new() + @return 0 if successful, or -1 if an error occurred + @see bufferevent_new() + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_base_set(struct event_base *base, struct bufferevent *bufev); + +/** + Return the event_base used by a bufferevent +*/ +EVENT2_EXPORT_SYMBOL +struct event_base *bufferevent_get_base(struct bufferevent *bev); + +/** + Assign a priority to a bufferevent. + + Only supported for socket bufferevents. + + @param bufev a bufferevent struct + @param pri the priority to be assigned + @return 0 if successful, or -1 if an error occurred + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_priority_set(struct bufferevent *bufev, int pri); + +/** + Return the priority of a bufferevent. + + Only supported for socket bufferevents + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_get_priority(const struct bufferevent *bufev); + +/** + Deallocate the storage associated with a bufferevent structure. + + If there is pending data to write on the bufferevent, it probably won't be + flushed before the bufferevent is freed. + + @param bufev the bufferevent structure to be freed. + */ +EVENT2_EXPORT_SYMBOL +void bufferevent_free(struct bufferevent *bufev); + + +/** + Changes the callbacks for a bufferevent. + + @param bufev the bufferevent object for which to change callbacks + @param readcb callback to invoke when there is data to be read, or NULL if + no callback is desired + @param writecb callback to invoke when the file descriptor is ready for + writing, or NULL if no callback is desired + @param eventcb callback to invoke when there is an event on the file + descriptor + @param cbarg an argument that will be supplied to each of the callbacks + (readcb, writecb, and errorcb) + @see bufferevent_new() + */ +EVENT2_EXPORT_SYMBOL +void bufferevent_setcb(struct bufferevent *bufev, + bufferevent_data_cb readcb, bufferevent_data_cb writecb, + bufferevent_event_cb eventcb, void *cbarg); + +/** + Retrieves the callbacks for a bufferevent. + + @param bufev the bufferevent to examine. + @param readcb_ptr if readcb_ptr is nonnull, *readcb_ptr is set to the current + read callback for the bufferevent. + @param writecb_ptr if writecb_ptr is nonnull, *writecb_ptr is set to the + current write callback for the bufferevent. + @param eventcb_ptr if eventcb_ptr is nonnull, *eventcb_ptr is set to the + current event callback for the bufferevent. + @param cbarg_ptr if cbarg_ptr is nonnull, *cbarg_ptr is set to the current + callback argument for the bufferevent. + @see buffervent_setcb() +*/ +EVENT2_EXPORT_SYMBOL +void bufferevent_getcb(struct bufferevent *bufev, + bufferevent_data_cb *readcb_ptr, + bufferevent_data_cb *writecb_ptr, + bufferevent_event_cb *eventcb_ptr, + void **cbarg_ptr); + +/** + Changes the file descriptor on which the bufferevent operates. + Not supported for all bufferevent types. + + @param bufev the bufferevent object for which to change the file descriptor + @param fd the file descriptor to operate on +*/ +EVENT2_EXPORT_SYMBOL +int bufferevent_setfd(struct bufferevent *bufev, evutil_socket_t fd); + +/** + Returns the file descriptor associated with a bufferevent, or -1 if + no file descriptor is associated with the bufferevent. + */ +EVENT2_EXPORT_SYMBOL +evutil_socket_t bufferevent_getfd(struct bufferevent *bufev); + +/** + Returns the underlying bufferevent associated with a bufferevent (if + the bufferevent is a wrapper), or NULL if there is no underlying bufferevent. + */ +EVENT2_EXPORT_SYMBOL +struct bufferevent *bufferevent_get_underlying(struct bufferevent *bufev); + +/** + Write data to a bufferevent buffer. + + The bufferevent_write() function can be used to write data to the file + descriptor. The data is appended to the output buffer and written to the + descriptor automatically as it becomes available for writing. + + @param bufev the bufferevent to be written to + @param data a pointer to the data to be written + @param size the length of the data, in bytes + @return 0 if successful, or -1 if an error occurred + @see bufferevent_write_buffer() + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_write(struct bufferevent *bufev, + const void *data, size_t size); + + +/** + Write data from an evbuffer to a bufferevent buffer. The evbuffer is + being drained as a result. + + @param bufev the bufferevent to be written to + @param buf the evbuffer to be written + @return 0 if successful, or -1 if an error occurred + @see bufferevent_write() + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf); + + +/** + Read data from a bufferevent buffer. + + The bufferevent_read() function is used to read data from the input buffer. + + @param bufev the bufferevent to be read from + @param data pointer to a buffer that will store the data + @param size the size of the data buffer, in bytes + @return the amount of data read, in bytes. + */ +EVENT2_EXPORT_SYMBOL +size_t bufferevent_read(struct bufferevent *bufev, void *data, size_t size); + +/** + Read data from a bufferevent buffer into an evbuffer. This avoids + memory copies. + + @param bufev the bufferevent to be read from + @param buf the evbuffer to which to add data + @return 0 if successful, or -1 if an error occurred. + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_read_buffer(struct bufferevent *bufev, struct evbuffer *buf); + +/** + Returns the input buffer. + + The user MUST NOT set the callback on this buffer. + + @param bufev the bufferevent from which to get the evbuffer + @return the evbuffer object for the input buffer + */ + +EVENT2_EXPORT_SYMBOL +struct evbuffer *bufferevent_get_input(struct bufferevent *bufev); + +/** + Returns the output buffer. + + The user MUST NOT set the callback on this buffer. + + When filters are being used, the filters need to be manually + triggered if the output buffer was manipulated. + + @param bufev the bufferevent from which to get the evbuffer + @return the evbuffer object for the output buffer + */ + +EVENT2_EXPORT_SYMBOL +struct evbuffer *bufferevent_get_output(struct bufferevent *bufev); + +/** + Enable a bufferevent. + + @param bufev the bufferevent to be enabled + @param event any combination of EV_READ | EV_WRITE. + @return 0 if successful, or -1 if an error occurred + @see bufferevent_disable() + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_enable(struct bufferevent *bufev, short event); + +/** + Disable a bufferevent. + + @param bufev the bufferevent to be disabled + @param event any combination of EV_READ | EV_WRITE. + @return 0 if successful, or -1 if an error occurred + @see bufferevent_enable() + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_disable(struct bufferevent *bufev, short event); + +/** + Return the events that are enabled on a given bufferevent. + + @param bufev the bufferevent to inspect + @return A combination of EV_READ | EV_WRITE + */ +EVENT2_EXPORT_SYMBOL +short bufferevent_get_enabled(struct bufferevent *bufev); + +/** + Set the read and write timeout for a bufferevent. + + A bufferevent's timeout will fire the first time that the indicated + amount of time has elapsed since a successful read or write operation, + during which the bufferevent was trying to read or write. + + (In other words, if reading or writing is disabled, or if the + bufferevent's read or write operation has been suspended because + there's no data to write, or not enough banwidth, or so on, the + timeout isn't active. The timeout only becomes active when we we're + willing to actually read or write.) + + Calling bufferevent_enable or setting a timeout for a bufferevent + whose timeout is already pending resets its timeout. + + If the timeout elapses, the corresponding operation (EV_READ or + EV_WRITE) becomes disabled until you re-enable it again. The + bufferevent's event callback is called with the + BEV_EVENT_TIMEOUT|BEV_EVENT_READING or + BEV_EVENT_TIMEOUT|BEV_EVENT_WRITING. + + @param bufev the bufferevent to be modified + @param timeout_read the read timeout, or NULL + @param timeout_write the write timeout, or NULL + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_set_timeouts(struct bufferevent *bufev, + const struct timeval *timeout_read, const struct timeval *timeout_write); + +/** + Sets the watermarks for read and write events. + + On input, a bufferevent does not invoke the user read callback unless + there is at least low watermark data in the buffer. If the read buffer + is beyond the high watermark, the bufferevent stops reading from the network. + + On output, the user write callback is invoked whenever the buffered data + falls below the low watermark. Filters that write to this bufev will try + not to write more bytes to this buffer than the high watermark would allow, + except when flushing. + + @param bufev the bufferevent to be modified + @param events EV_READ, EV_WRITE or both + @param lowmark the lower watermark to set + @param highmark the high watermark to set +*/ + +EVENT2_EXPORT_SYMBOL +void bufferevent_setwatermark(struct bufferevent *bufev, short events, + size_t lowmark, size_t highmark); + +/** + Retrieves the watermarks for read or write events. + Returns non-zero if events contains not only EV_READ or EV_WRITE. + Returns zero if events equal EV_READ or EV_WRITE + + @param bufev the bufferevent to be examined + @param events EV_READ or EV_WRITE + @param lowmark receives the lower watermark if not NULL + @param highmark receives the high watermark if not NULL +*/ +EVENT2_EXPORT_SYMBOL +int bufferevent_getwatermark(struct bufferevent *bufev, short events, + size_t *lowmark, size_t *highmark); + +/** + Acquire the lock on a bufferevent. Has no effect if locking was not + enabled with BEV_OPT_THREADSAFE. + */ +EVENT2_EXPORT_SYMBOL +void bufferevent_lock(struct bufferevent *bufev); + +/** + Release the lock on a bufferevent. Has no effect if locking was not + enabled with BEV_OPT_THREADSAFE. + */ +EVENT2_EXPORT_SYMBOL +void bufferevent_unlock(struct bufferevent *bufev); + + +/** + * Public interface to manually increase the reference count of a bufferevent + * this is useful in situations where a user may reference the bufferevent + * somewhere eles (unknown to libevent) + * + * @param bufev the bufferevent to increase the refcount on + * + */ +EVENT2_EXPORT_SYMBOL +void bufferevent_incref(struct bufferevent *bufev); + +/** + * Public interface to manually decrement the reference count of a bufferevent + * + * Warning: make sure you know what you're doing. This is mainly used in + * conjunction with bufferevent_incref(). This will free up all data associated + * with a bufferevent if the reference count hits 0. + * + * @param bufev the bufferevent to decrement the refcount on + * + * @return 1 if the bufferevent was freed, otherwise 0 (still referenced) + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_decref(struct bufferevent *bufev); + +/** + Flags that can be passed into filters to let them know how to + deal with the incoming data. +*/ +enum bufferevent_flush_mode { + /** usually set when processing data */ + BEV_NORMAL = 0, + + /** want to checkpoint all data sent. */ + BEV_FLUSH = 1, + + /** encountered EOF on read or done sending data */ + BEV_FINISHED = 2 +}; + +/** + Triggers the bufferevent to produce more data if possible. + + @param bufev the bufferevent object + @param iotype either EV_READ or EV_WRITE or both. + @param mode either BEV_NORMAL or BEV_FLUSH or BEV_FINISHED + @return -1 on failure, 0 if no data was produces, 1 if data was produced + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_flush(struct bufferevent *bufev, + short iotype, + enum bufferevent_flush_mode mode); + +/** + Flags for bufferevent_trigger(_event) that modify when and how to trigger + the callback. +*/ +enum bufferevent_trigger_options { + /** trigger the callback regardless of the watermarks */ + BEV_TRIG_IGNORE_WATERMARKS = (1<<16), + + /** defer even if the callbacks are not */ + BEV_TRIG_DEFER_CALLBACKS = BEV_OPT_DEFER_CALLBACKS + + /* (Note: for internal reasons, these need to be disjoint from + * bufferevent_options, except when they mean the same thing. */ +}; + +/** + Triggers bufferevent data callbacks. + + The function will honor watermarks unless options contain + BEV_TRIG_IGNORE_WATERMARKS. If the options contain BEV_OPT_DEFER_CALLBACKS, + the callbacks are deferred. + + @param bufev the bufferevent object + @param iotype either EV_READ or EV_WRITE or both. + @param options + */ +EVENT2_EXPORT_SYMBOL +void bufferevent_trigger(struct bufferevent *bufev, short iotype, + int options); + +/** + Triggers the bufferevent event callback. + + If the options contain BEV_OPT_DEFER_CALLBACKS, the callbacks are deferred. + + @param bufev the bufferevent object + @param what the flags to pass onto the event callback + @param options + */ +EVENT2_EXPORT_SYMBOL +void bufferevent_trigger_event(struct bufferevent *bufev, short what, + int options); + +/** + @name Filtering support + + @{ +*/ +/** + Values that filters can return. + */ +enum bufferevent_filter_result { + /** everything is okay */ + BEV_OK = 0, + + /** the filter needs to read more data before output */ + BEV_NEED_MORE = 1, + + /** the filter encountered a critical error, no further data + can be processed. */ + BEV_ERROR = 2 +}; + +/** A callback function to implement a filter for a bufferevent. + + @param src An evbuffer to drain data from. + @param dst An evbuffer to add data to. + @param limit A suggested upper bound of bytes to write to dst. + The filter may ignore this value, but doing so means that + it will overflow the high-water mark associated with dst. + -1 means "no limit". + @param mode Whether we should write data as may be convenient + (BEV_NORMAL), or flush as much data as we can (BEV_FLUSH), + or flush as much as we can, possibly including an end-of-stream + marker (BEV_FINISH). + @param ctx A user-supplied pointer. + + @return BEV_OK if we wrote some data; BEV_NEED_MORE if we can't + produce any more output until we get some input; and BEV_ERROR + on an error. + */ +typedef enum bufferevent_filter_result (*bufferevent_filter_cb)( + struct evbuffer *src, struct evbuffer *dst, ev_ssize_t dst_limit, + enum bufferevent_flush_mode mode, void *ctx); + +/** + Allocate a new filtering bufferevent on top of an existing bufferevent. + + @param underlying the underlying bufferevent. + @param input_filter The filter to apply to data we read from the underlying + bufferevent + @param output_filter The filer to apply to data we write to the underlying + bufferevent + @param options A bitfield of bufferevent options. + @param free_context A function to use to free the filter context when + this bufferevent is freed. + @param ctx A context pointer to pass to the filter functions. + */ +EVENT2_EXPORT_SYMBOL +struct bufferevent * +bufferevent_filter_new(struct bufferevent *underlying, + bufferevent_filter_cb input_filter, + bufferevent_filter_cb output_filter, + int options, + void (*free_context)(void *), + void *ctx); +/**@}*/ + +/** + Allocate a pair of linked bufferevents. The bufferevents behave as would + two bufferevent_sock instances connected to opposite ends of a + socketpair(), except that no internal socketpair is allocated. + + @param base The event base to associate with the socketpair. + @param options A set of options for this bufferevent + @param pair A pointer to an array to hold the two new bufferevent objects. + @return 0 on success, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_pair_new(struct event_base *base, int options, + struct bufferevent *pair[2]); + +/** + Given one bufferevent returned by bufferevent_pair_new(), returns the + other one if it still exists. Otherwise returns NULL. + */ +EVENT2_EXPORT_SYMBOL +struct bufferevent *bufferevent_pair_get_partner(struct bufferevent *bev); + +/** + Abstract type used to configure rate-limiting on a bufferevent or a group + of bufferevents. + */ +struct ev_token_bucket_cfg; + +/** + A group of bufferevents which are configured to respect the same rate + limit. +*/ +struct bufferevent_rate_limit_group; + +/** Maximum configurable rate- or burst-limit. */ +#define EV_RATE_LIMIT_MAX EV_SSIZE_MAX + +/** + Initialize and return a new object to configure the rate-limiting behavior + of bufferevents. + + @param read_rate The maximum number of bytes to read per tick on + average. + @param read_burst The maximum number of bytes to read in any single tick. + @param write_rate The maximum number of bytes to write per tick on + average. + @param write_burst The maximum number of bytes to write in any single tick. + @param tick_len The length of a single tick. Defaults to one second. + Any fractions of a millisecond are ignored. + + Note that all rate-limits hare are currently best-effort: future versions + of Libevent may implement them more tightly. + */ +EVENT2_EXPORT_SYMBOL +struct ev_token_bucket_cfg *ev_token_bucket_cfg_new( + size_t read_rate, size_t read_burst, + size_t write_rate, size_t write_burst, + const struct timeval *tick_len); + +/** Free all storage held in 'cfg'. + + Note: 'cfg' is not currently reference-counted; it is not safe to free it + until no bufferevent is using it. + */ +EVENT2_EXPORT_SYMBOL +void ev_token_bucket_cfg_free(struct ev_token_bucket_cfg *cfg); + +/** + Set the rate-limit of a the bufferevent 'bev' to the one specified in + 'cfg'. If 'cfg' is NULL, disable any per-bufferevent rate-limiting on + 'bev'. + + Note that only some bufferevent types currently respect rate-limiting. + They are: socket-based bufferevents (normal and IOCP-based), and SSL-based + bufferevents. + + Return 0 on sucess, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_set_rate_limit(struct bufferevent *bev, + struct ev_token_bucket_cfg *cfg); + +/** + Create a new rate-limit group for bufferevents. A rate-limit group + constrains the maximum number of bytes sent and received, in toto, + by all of its bufferevents. + + @param base An event_base to run any necessary timeouts for the group. + Note that all bufferevents in the group do not necessarily need to share + this event_base. + @param cfg The rate-limit for this group. + + Note that all rate-limits hare are currently best-effort: future versions + of Libevent may implement them more tightly. + + Note also that only some bufferevent types currently respect rate-limiting. + They are: socket-based bufferevents (normal and IOCP-based), and SSL-based + bufferevents. + */ +EVENT2_EXPORT_SYMBOL +struct bufferevent_rate_limit_group *bufferevent_rate_limit_group_new( + struct event_base *base, + const struct ev_token_bucket_cfg *cfg); +/** + Change the rate-limiting settings for a given rate-limiting group. + + Return 0 on success, -1 on failure. +*/ +EVENT2_EXPORT_SYMBOL +int bufferevent_rate_limit_group_set_cfg( + struct bufferevent_rate_limit_group *, + const struct ev_token_bucket_cfg *); + +/** + Change the smallest quantum we're willing to allocate to any single + bufferevent in a group for reading or writing at a time. + + The rationale is that, because of TCP/IP protocol overheads and kernel + behavior, if a rate-limiting group is so tight on bandwidth that you're + only willing to send 1 byte per tick per bufferevent, you might instead + want to batch up the reads and writes so that you send N bytes per + 1/N of the bufferevents (chosen at random) each tick, so you still wind + up send 1 byte per tick per bufferevent on average, but you don't send + so many tiny packets. + + The default min-share is currently 64 bytes. + + Returns 0 on success, -1 on faulre. + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_rate_limit_group_set_min_share( + struct bufferevent_rate_limit_group *, size_t); + +/** + Free a rate-limiting group. The group must have no members when + this function is called. +*/ +EVENT2_EXPORT_SYMBOL +void bufferevent_rate_limit_group_free(struct bufferevent_rate_limit_group *); + +/** + Add 'bev' to the list of bufferevents whose aggregate reading and writing + is restricted by 'g'. If 'g' is NULL, remove 'bev' from its current group. + + A bufferevent may belong to no more than one rate-limit group at a time. + If 'bev' is already a member of a group, it will be removed from its old + group before being added to 'g'. + + Return 0 on success and -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_add_to_rate_limit_group(struct bufferevent *bev, + struct bufferevent_rate_limit_group *g); + +/** Remove 'bev' from its current rate-limit group (if any). */ +EVENT2_EXPORT_SYMBOL +int bufferevent_remove_from_rate_limit_group(struct bufferevent *bev); + +/** + Set the size limit for single read operation. + + Set to 0 for a reasonable default. + + Return 0 on success and -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_set_max_single_read(struct bufferevent *bev, size_t size); + +/** + Set the size limit for single write operation. + + Set to 0 for a reasonable default. + + Return 0 on success and -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_set_max_single_write(struct bufferevent *bev, size_t size); + +/** Get the current size limit for single read operation. */ +EVENT2_EXPORT_SYMBOL +ev_ssize_t bufferevent_get_max_single_read(struct bufferevent *bev); + +/** Get the current size limit for single write operation. */ +EVENT2_EXPORT_SYMBOL +ev_ssize_t bufferevent_get_max_single_write(struct bufferevent *bev); + +/** + @name Rate limit inspection + + Return the current read or write bucket size for a bufferevent. + If it is not configured with a per-bufferevent ratelimit, return + EV_SSIZE_MAX. This function does not inspect the group limit, if any. + Note that it can return a negative value if the bufferevent has been + made to read or write more than its limit. + + @{ + */ +EVENT2_EXPORT_SYMBOL +ev_ssize_t bufferevent_get_read_limit(struct bufferevent *bev); +EVENT2_EXPORT_SYMBOL +ev_ssize_t bufferevent_get_write_limit(struct bufferevent *bev); +/*@}*/ + +EVENT2_EXPORT_SYMBOL +ev_ssize_t bufferevent_get_max_to_read(struct bufferevent *bev); +EVENT2_EXPORT_SYMBOL +ev_ssize_t bufferevent_get_max_to_write(struct bufferevent *bev); + +EVENT2_EXPORT_SYMBOL +const struct ev_token_bucket_cfg *bufferevent_get_token_bucket_cfg(const struct bufferevent * bev); + +/** + @name Group Rate limit inspection + + Return the read or write bucket size for a bufferevent rate limit + group. Note that it can return a negative value if bufferevents in + the group have been made to read or write more than their limits. + + @{ + */ +EVENT2_EXPORT_SYMBOL +ev_ssize_t bufferevent_rate_limit_group_get_read_limit( + struct bufferevent_rate_limit_group *); +EVENT2_EXPORT_SYMBOL +ev_ssize_t bufferevent_rate_limit_group_get_write_limit( + struct bufferevent_rate_limit_group *); +/*@}*/ + +/** + @name Rate limit manipulation + + Subtract a number of bytes from a bufferevent's read or write bucket. + The decrement value can be negative, if you want to manually refill + the bucket. If the change puts the bucket above or below zero, the + bufferevent will resume or suspend reading writing as appropriate. + These functions make no change in the buckets for the bufferevent's + group, if any. + + Returns 0 on success, -1 on internal error. + + @{ + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_decrement_read_limit(struct bufferevent *bev, ev_ssize_t decr); +EVENT2_EXPORT_SYMBOL +int bufferevent_decrement_write_limit(struct bufferevent *bev, ev_ssize_t decr); +/*@}*/ + +/** + @name Group rate limit manipulation + + Subtract a number of bytes from a bufferevent rate-limiting group's + read or write bucket. The decrement value can be negative, if you + want to manually refill the bucket. If the change puts the bucket + above or below zero, the bufferevents in the group will resume or + suspend reading writing as appropriate. + + Returns 0 on success, -1 on internal error. + + @{ + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_rate_limit_group_decrement_read( + struct bufferevent_rate_limit_group *, ev_ssize_t); +EVENT2_EXPORT_SYMBOL +int bufferevent_rate_limit_group_decrement_write( + struct bufferevent_rate_limit_group *, ev_ssize_t); +/*@}*/ + + +/** + * Inspect the total bytes read/written on a group. + * + * Set the variable pointed to by total_read_out to the total number of bytes + * ever read on grp, and the variable pointed to by total_written_out to the + * total number of bytes ever written on grp. */ +EVENT2_EXPORT_SYMBOL +void bufferevent_rate_limit_group_get_totals( + struct bufferevent_rate_limit_group *grp, + ev_uint64_t *total_read_out, ev_uint64_t *total_written_out); + +/** + * Reset the total bytes read/written on a group. + * + * Reset the number of bytes read or written on grp as given by + * bufferevent_rate_limit_group_reset_totals(). */ +EVENT2_EXPORT_SYMBOL +void +bufferevent_rate_limit_group_reset_totals( + struct bufferevent_rate_limit_group *grp); + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_BUFFEREVENT_H_INCLUDED_ */ diff --git a/src/include/event2/bufferevent_compat.h b/src/include/event2/bufferevent_compat.h new file mode 100644 index 0000000..6548204 --- /dev/null +++ b/src/include/event2/bufferevent_compat.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2007-2012 Niels Provos, Nick Mathewson + * Copyright (c) 2000-2007 Niels Provos <[email protected]> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EVENT2_BUFFEREVENT_COMPAT_H_INCLUDED_ +#define EVENT2_BUFFEREVENT_COMPAT_H_INCLUDED_ + +#define evbuffercb bufferevent_data_cb +#define everrorcb bufferevent_event_cb + +/** + Create a new bufferevent for an fd. + + This function is deprecated. Use bufferevent_socket_new and + bufferevent_set_callbacks instead. + + Libevent provides an abstraction on top of the regular event callbacks. + This abstraction is called a buffered event. A buffered event provides + input and output buffers that get filled and drained automatically. The + user of a buffered event no longer deals directly with the I/O, but + instead is reading from input and writing to output buffers. + + Once initialized, the bufferevent structure can be used repeatedly with + bufferevent_enable() and bufferevent_disable(). + + When read enabled the bufferevent will try to read from the file descriptor + and call the read callback. The write callback is executed whenever the + output buffer is drained below the write low watermark, which is 0 by + default. + + If multiple bases are in use, bufferevent_base_set() must be called before + enabling the bufferevent for the first time. + + @deprecated This function is deprecated because it uses the current + event base, and as such can be error prone for multithreaded programs. + Use bufferevent_socket_new() instead. + + @param fd the file descriptor from which data is read and written to. + This file descriptor is not allowed to be a pipe(2). + @param readcb callback to invoke when there is data to be read, or NULL if + no callback is desired + @param writecb callback to invoke when the file descriptor is ready for + writing, or NULL if no callback is desired + @param errorcb callback to invoke when there is an error on the file + descriptor + @param cbarg an argument that will be supplied to each of the callbacks + (readcb, writecb, and errorcb) + @return a pointer to a newly allocated bufferevent struct, or NULL if an + error occurred + @see bufferevent_base_set(), bufferevent_free() + */ +struct bufferevent *bufferevent_new(evutil_socket_t fd, + evbuffercb readcb, evbuffercb writecb, everrorcb errorcb, void *cbarg); + + +/** + Set the read and write timeout for a buffered event. + + @param bufev the bufferevent to be modified + @param timeout_read the read timeout + @param timeout_write the write timeout + */ +void bufferevent_settimeout(struct bufferevent *bufev, + int timeout_read, int timeout_write); + +#define EVBUFFER_READ BEV_EVENT_READING +#define EVBUFFER_WRITE BEV_EVENT_WRITING +#define EVBUFFER_EOF BEV_EVENT_EOF +#define EVBUFFER_ERROR BEV_EVENT_ERROR +#define EVBUFFER_TIMEOUT BEV_EVENT_TIMEOUT + +/** macro for getting access to the input buffer of a bufferevent */ +#define EVBUFFER_INPUT(x) bufferevent_get_input(x) +/** macro for getting access to the output buffer of a bufferevent */ +#define EVBUFFER_OUTPUT(x) bufferevent_get_output(x) + +#endif diff --git a/src/include/event2/bufferevent_ssl.h b/src/include/event2/bufferevent_ssl.h new file mode 100644 index 0000000..bf39b84 --- /dev/null +++ b/src/include/event2/bufferevent_ssl.h @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EVENT2_BUFFEREVENT_SSL_H_INCLUDED_ +#define EVENT2_BUFFEREVENT_SSL_H_INCLUDED_ + +/** @file event2/bufferevent_ssl.h + + OpenSSL support for bufferevents. + */ +#include <event2/visibility.h> +#include <event2/event-config.h> +#include <event2/bufferevent.h> +#include <event2/util.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* This is what openssl's SSL objects are underneath. */ +struct ssl_st; + +/** + The state of an SSL object to be used when creating a new + SSL bufferevent. + */ +enum bufferevent_ssl_state { + BUFFEREVENT_SSL_OPEN = 0, + BUFFEREVENT_SSL_CONNECTING = 1, + BUFFEREVENT_SSL_ACCEPTING = 2 +}; + +#if defined(EVENT__HAVE_OPENSSL) || defined(EVENT_IN_DOXYGEN_) +/** + Create a new SSL bufferevent to send its data over another bufferevent. + + @param base An event_base to use to detect reading and writing. It + must also be the base for the underlying bufferevent. + @param underlying A socket to use for this SSL + @param ssl A SSL* object from openssl. + @param state The current state of the SSL connection + @param options One or more bufferevent_options + @return A new bufferevent on success, or NULL on failure +*/ +EVENT2_EXPORT_SYMBOL +struct bufferevent * +bufferevent_openssl_filter_new(struct event_base *base, + struct bufferevent *underlying, + struct ssl_st *ssl, + enum bufferevent_ssl_state state, + int options); + +/** + Create a new SSL bufferevent to send its data over an SSL * on a socket. + + @param base An event_base to use to detect reading and writing + @param fd A socket to use for this SSL + @param ssl A SSL* object from openssl. + @param state The current state of the SSL connection + @param options One or more bufferevent_options + @return A new bufferevent on success, or NULL on failure. +*/ +EVENT2_EXPORT_SYMBOL +struct bufferevent * +bufferevent_openssl_socket_new(struct event_base *base, + evutil_socket_t fd, + struct ssl_st *ssl, + enum bufferevent_ssl_state state, + int options); + +/** Control how to report dirty SSL shutdowns. + + If the peer (or the network, or an attacker) closes the TCP + connection before closing the SSL channel, and the protocol is SSL >= v3, + this is a "dirty" shutdown. If allow_dirty_shutdown is 0 (default), + this is reported as BEV_EVENT_ERROR. + + If instead allow_dirty_shutdown=1, a dirty shutdown is reported as + BEV_EVENT_EOF. + + (Note that if the protocol is < SSLv3, you will always receive + BEV_EVENT_EOF, since SSL 2 and earlier cannot distinguish a secure + connection close from a dirty one. This is one reason (among many) + not to use SSL 2.) +*/ + +EVENT2_EXPORT_SYMBOL +int bufferevent_openssl_get_allow_dirty_shutdown(struct bufferevent *bev); +EVENT2_EXPORT_SYMBOL +void bufferevent_openssl_set_allow_dirty_shutdown(struct bufferevent *bev, + int allow_dirty_shutdown); + +/** Return the underlying openssl SSL * object for an SSL bufferevent. */ +EVENT2_EXPORT_SYMBOL +struct ssl_st * +bufferevent_openssl_get_ssl(struct bufferevent *bufev); + +/** Tells a bufferevent to begin SSL renegotiation. */ +EVENT2_EXPORT_SYMBOL +int bufferevent_ssl_renegotiate(struct bufferevent *bev); + +/** Return the most recent OpenSSL error reported on an SSL bufferevent. */ +EVENT2_EXPORT_SYMBOL +unsigned long bufferevent_get_openssl_error(struct bufferevent *bev); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_BUFFEREVENT_SSL_H_INCLUDED_ */ diff --git a/src/include/event2/bufferevent_struct.h b/src/include/event2/bufferevent_struct.h new file mode 100644 index 0000000..e84c082 --- /dev/null +++ b/src/include/event2/bufferevent_struct.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2000-2007 Niels Provos <[email protected]> + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EVENT2_BUFFEREVENT_STRUCT_H_INCLUDED_ +#define EVENT2_BUFFEREVENT_STRUCT_H_INCLUDED_ + +/** @file event2/bufferevent_struct.h + + Data structures for bufferevents. Using these structures may hurt forward + compatibility with later versions of Libevent: be careful! + + @deprecated Use of bufferevent_struct.h is completely deprecated; these + structures are only exposed for backward compatibility with programs + written before Libevent 2.0 that used them. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <event2/event-config.h> +#ifdef EVENT__HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef EVENT__HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + +/* For int types. */ +#include <event2/util.h> +/* For struct event */ +#include <event2/event_struct.h> + +struct event_watermark { + size_t low; + size_t high; +}; + +/** + Shared implementation of a bufferevent. + + This type is exposed only because it was exposed in previous versions, + and some people's code may rely on manipulating it. Otherwise, you + should really not rely on the layout, size, or contents of this structure: + it is fairly volatile, and WILL change in future versions of the code. +**/ +struct bufferevent { + /** Event base for which this bufferevent was created. */ + struct event_base *ev_base; + /** Pointer to a table of function pointers to set up how this + bufferevent behaves. */ + const struct bufferevent_ops *be_ops; + + /** A read event that triggers when a timeout has happened or a socket + is ready to read data. Only used by some subtypes of + bufferevent. */ + struct event ev_read; + /** A write event that triggers when a timeout has happened or a socket + is ready to write data. Only used by some subtypes of + bufferevent. */ + struct event ev_write; + + /** An input buffer. Only the bufferevent is allowed to add data to + this buffer, though the user is allowed to drain it. */ + struct evbuffer *input; + + /** An input buffer. Only the bufferevent is allowed to drain data + from this buffer, though the user is allowed to add it. */ + struct evbuffer *output; + + struct event_watermark wm_read; + struct event_watermark wm_write; + + bufferevent_data_cb readcb; + bufferevent_data_cb writecb; + /* This should be called 'eventcb', but renaming it would break + * backward compatibility */ + bufferevent_event_cb errorcb; + void *cbarg; + + struct timeval timeout_read; + struct timeval timeout_write; + + /** Events that are currently enabled: currently EV_READ and EV_WRITE + are supported. */ + short enabled; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_BUFFEREVENT_STRUCT_H_INCLUDED_ */ diff --git a/src/include/event2/dns.h b/src/include/event2/dns.h new file mode 100644 index 0000000..17cd86a --- /dev/null +++ b/src/include/event2/dns.h @@ -0,0 +1,717 @@ +/* + * Copyright (c) 2006-2007 Niels Provos <[email protected]> + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * The original DNS code is due to Adam Langley with heavy + * modifications by Nick Mathewson. Adam put his DNS software in the + * public domain. You can find his original copyright below. Please, + * aware that the code as part of Libevent is governed by the 3-clause + * BSD license above. + * + * This software is Public Domain. To view a copy of the public domain dedication, + * visit http://creativecommons.org/licenses/publicdomain/ or send a letter to + * Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. + * + * I ask and expect, but do not require, that all derivative works contain an + * attribution similar to: + * Parts developed by Adam Langley <[email protected]> + * + * You may wish to replace the word "Parts" with something else depending on + * the amount of original code. + * + * (Derivative works does not include programs which link against, run or include + * the source verbatim in their source distributions) + */ + +/** @file event2/dns.h + * + * Welcome, gentle reader + * + * Async DNS lookups are really a whole lot harder than they should be, + * mostly stemming from the fact that the libc resolver has never been + * very good at them. Before you use this library you should see if libc + * can do the job for you with the modern async call getaddrinfo_a + * (see http://www.imperialviolet.org/page25.html#e498). Otherwise, + * please continue. + * + * The library keeps track of the state of nameservers and will avoid + * them when they go down. Otherwise it will round robin between them. + * + * Quick start guide: + * #include "evdns.h" + * void callback(int result, char type, int count, int ttl, + * void *addresses, void *arg); + * evdns_resolv_conf_parse(DNS_OPTIONS_ALL, "/etc/resolv.conf"); + * evdns_resolve("www.hostname.com", 0, callback, NULL); + * + * When the lookup is complete the callback function is called. The + * first argument will be one of the DNS_ERR_* defines in evdns.h. + * Hopefully it will be DNS_ERR_NONE, in which case type will be + * DNS_IPv4_A, count will be the number of IP addresses, ttl is the time + * which the data can be cached for (in seconds), addresses will point + * to an array of uint32_t's and arg will be whatever you passed to + * evdns_resolve. + * + * Searching: + * + * In order for this library to be a good replacement for glibc's resolver it + * supports searching. This involves setting a list of default domains, in + * which names will be queried for. The number of dots in the query name + * determines the order in which this list is used. + * + * Searching appears to be a single lookup from the point of view of the API, + * although many DNS queries may be generated from a single call to + * evdns_resolve. Searching can also drastically slow down the resolution + * of names. + * + * To disable searching: + * 1. Never set it up. If you never call evdns_resolv_conf_parse or + * evdns_search_add then no searching will occur. + * + * 2. If you do call evdns_resolv_conf_parse then don't pass + * DNS_OPTION_SEARCH (or DNS_OPTIONS_ALL, which implies it). + * + * 3. When calling evdns_resolve, pass the DNS_QUERY_NO_SEARCH flag. + * + * The order of searches depends on the number of dots in the name. If the + * number is greater than the ndots setting then the names is first tried + * globally. Otherwise each search domain is appended in turn. + * + * The ndots setting can either be set from a resolv.conf, or by calling + * evdns_search_ndots_set. + * + * For example, with ndots set to 1 (the default) and a search domain list of + * ["myhome.net"]: + * Query: www + * Order: www.myhome.net, www. + * + * Query: www.abc + * Order: www.abc., www.abc.myhome.net + * + * Internals: + * + * Requests are kept in two queues. The first is the inflight queue. In + * this queue requests have an allocated transaction id and nameserver. + * They will soon be transmitted if they haven't already been. + * + * The second is the waiting queue. The size of the inflight ring is + * limited and all other requests wait in waiting queue for space. This + * bounds the number of concurrent requests so that we don't flood the + * nameserver. Several algorithms require a full walk of the inflight + * queue and so bounding its size keeps thing going nicely under huge + * (many thousands of requests) loads. + * + * If a nameserver loses too many requests it is considered down and we + * try not to use it. After a while we send a probe to that nameserver + * (a lookup for google.com) and, if it replies, we consider it working + * again. If the nameserver fails a probe we wait longer to try again + * with the next probe. + */ + +#ifndef EVENT2_DNS_H_INCLUDED_ +#define EVENT2_DNS_H_INCLUDED_ + +#include <event2/visibility.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* For integer types. */ +#include <event2/util.h> + +/** Error codes 0-5 are as described in RFC 1035. */ +#define DNS_ERR_NONE 0 +/** The name server was unable to interpret the query */ +#define DNS_ERR_FORMAT 1 +/** The name server was unable to process this query due to a problem with the + * name server */ +#define DNS_ERR_SERVERFAILED 2 +/** The domain name does not exist */ +#define DNS_ERR_NOTEXIST 3 +/** The name server does not support the requested kind of query */ +#define DNS_ERR_NOTIMPL 4 +/** The name server refuses to reform the specified operation for policy + * reasons */ +#define DNS_ERR_REFUSED 5 +/** The reply was truncated or ill-formatted */ +#define DNS_ERR_TRUNCATED 65 +/** An unknown error occurred */ +#define DNS_ERR_UNKNOWN 66 +/** Communication with the server timed out */ +#define DNS_ERR_TIMEOUT 67 +/** The request was canceled because the DNS subsystem was shut down. */ +#define DNS_ERR_SHUTDOWN 68 +/** The request was canceled via a call to evdns_cancel_request */ +#define DNS_ERR_CANCEL 69 +/** There were no answers and no error condition in the DNS packet. + * This can happen when you ask for an address that exists, but a record + * type that doesn't. */ +#define DNS_ERR_NODATA 70 + +#define DNS_IPv4_A 1 +#define DNS_PTR 2 +#define DNS_IPv6_AAAA 3 + +#define DNS_QUERY_NO_SEARCH 1 + +#define DNS_OPTION_SEARCH 1 +#define DNS_OPTION_NAMESERVERS 2 +#define DNS_OPTION_MISC 4 +#define DNS_OPTION_HOSTSFILE 8 +#define DNS_OPTIONS_ALL 15 + +/* Obsolete name for DNS_QUERY_NO_SEARCH */ +#define DNS_NO_SEARCH DNS_QUERY_NO_SEARCH + +/** + * The callback that contains the results from a lookup. + * - result is one of the DNS_ERR_* values (DNS_ERR_NONE for success) + * - type is either DNS_IPv4_A or DNS_PTR or DNS_IPv6_AAAA + * - count contains the number of addresses of form type + * - ttl is the number of seconds the resolution may be cached for. + * - addresses needs to be cast according to type. It will be an array of + * 4-byte sequences for ipv4, or an array of 16-byte sequences for ipv6, + * or a nul-terminated string for PTR. + */ +typedef void (*evdns_callback_type) (int result, char type, int count, int ttl, void *addresses, void *arg); + +struct evdns_base; +struct event_base; + +/** Flag for evdns_base_new: process resolv.conf. */ +#define EVDNS_BASE_INITIALIZE_NAMESERVERS 1 +/** Flag for evdns_base_new: Do not prevent the libevent event loop from + * exiting when we have no active dns requests. */ +#define EVDNS_BASE_DISABLE_WHEN_INACTIVE 0x8000 + +/** + Initialize the asynchronous DNS library. + + This function initializes support for non-blocking name resolution by + calling evdns_resolv_conf_parse() on UNIX and + evdns_config_windows_nameservers() on Windows. + + @param event_base the event base to associate the dns client with + @param flags any of EVDNS_BASE_INITIALIZE_NAMESERVERS| + EVDNS_BASE_DISABLE_WHEN_INACTIVE + @return evdns_base object if successful, or NULL if an error occurred. + @see evdns_base_free() + */ +EVENT2_EXPORT_SYMBOL +struct evdns_base * evdns_base_new(struct event_base *event_base, int initialize_nameservers); + + +/** + Shut down the asynchronous DNS resolver and terminate all active requests. + + If the 'fail_requests' option is enabled, all active requests will return + an empty result with the error flag set to DNS_ERR_SHUTDOWN. Otherwise, + the requests will be silently discarded. + + @param evdns_base the evdns base to free + @param fail_requests if zero, active requests will be aborted; if non-zero, + active requests will return DNS_ERR_SHUTDOWN. + @see evdns_base_new() + */ +EVENT2_EXPORT_SYMBOL +void evdns_base_free(struct evdns_base *base, int fail_requests); + +/** + Remove all hosts entries that have been loaded into the event_base via + evdns_base_load_hosts or via event_base_resolv_conf_parse. + + @param evdns_base the evdns base to remove outdated host addresses from + */ +EVENT2_EXPORT_SYMBOL +void evdns_base_clear_host_addresses(struct evdns_base *base); + +/** + Convert a DNS error code to a string. + + @param err the DNS error code + @return a string containing an explanation of the error code +*/ +EVENT2_EXPORT_SYMBOL +const char *evdns_err_to_string(int err); + + +/** + Add a nameserver. + + The address should be an IPv4 address in network byte order. + The type of address is chosen so that it matches in_addr.s_addr. + + @param base the evdns_base to which to add the name server + @param address an IP address in network byte order + @return 0 if successful, or -1 if an error occurred + @see evdns_base_nameserver_ip_add() + */ +EVENT2_EXPORT_SYMBOL +int evdns_base_nameserver_add(struct evdns_base *base, + unsigned long int address); + +/** + Get the number of configured nameservers. + + This returns the number of configured nameservers (not necessarily the + number of running nameservers). This is useful for double-checking + whether our calls to the various nameserver configuration functions + have been successful. + + @param base the evdns_base to which to apply this operation + @return the number of configured nameservers + @see evdns_base_nameserver_add() + */ +EVENT2_EXPORT_SYMBOL +int evdns_base_count_nameservers(struct evdns_base *base); + +/** + Remove all configured nameservers, and suspend all pending resolves. + + Resolves will not necessarily be re-attempted until evdns_base_resume() is called. + + @param base the evdns_base to which to apply this operation + @return 0 if successful, or -1 if an error occurred + @see evdns_base_resume() + */ +EVENT2_EXPORT_SYMBOL +int evdns_base_clear_nameservers_and_suspend(struct evdns_base *base); + + +/** + Resume normal operation and continue any suspended resolve requests. + + Re-attempt resolves left in limbo after an earlier call to + evdns_base_clear_nameservers_and_suspend(). + + @param base the evdns_base to which to apply this operation + @return 0 if successful, or -1 if an error occurred + @see evdns_base_clear_nameservers_and_suspend() + */ +EVENT2_EXPORT_SYMBOL +int evdns_base_resume(struct evdns_base *base); + +/** + Add a nameserver by string address. + + This function parses a n IPv4 or IPv6 address from a string and adds it as a + nameserver. It supports the following formats: + - [IPv6Address]:port + - [IPv6Address] + - IPv6Address + - IPv4Address:port + - IPv4Address + + If no port is specified, it defaults to 53. + + @param base the evdns_base to which to apply this operation + @return 0 if successful, or -1 if an error occurred + @see evdns_base_nameserver_add() + */ +EVENT2_EXPORT_SYMBOL +int evdns_base_nameserver_ip_add(struct evdns_base *base, + const char *ip_as_string); + +/** + Add a nameserver by sockaddr. + **/ +EVENT2_EXPORT_SYMBOL +int +evdns_base_nameserver_sockaddr_add(struct evdns_base *base, + const struct sockaddr *sa, ev_socklen_t len, unsigned flags); + +struct evdns_request; + +/** + Lookup an A record for a given name. + + @param base the evdns_base to which to apply this operation + @param name a DNS hostname + @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query. + @param callback a callback function to invoke when the request is completed + @param ptr an argument to pass to the callback function + @return an evdns_request object if successful, or NULL if an error occurred. + @see evdns_resolve_ipv6(), evdns_resolve_reverse(), evdns_resolve_reverse_ipv6(), evdns_cancel_request() + */ +EVENT2_EXPORT_SYMBOL +struct evdns_request *evdns_base_resolve_ipv4(struct evdns_base *base, const char *name, int flags, evdns_callback_type callback, void *ptr); + +/** + Lookup an AAAA record for a given name. + + @param base the evdns_base to which to apply this operation + @param name a DNS hostname + @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query. + @param callback a callback function to invoke when the request is completed + @param ptr an argument to pass to the callback function + @return an evdns_request object if successful, or NULL if an error occurred. + @see evdns_resolve_ipv4(), evdns_resolve_reverse(), evdns_resolve_reverse_ipv6(), evdns_cancel_request() + */ +EVENT2_EXPORT_SYMBOL +struct evdns_request *evdns_base_resolve_ipv6(struct evdns_base *base, const char *name, int flags, evdns_callback_type callback, void *ptr); + +struct in_addr; +struct in6_addr; + +/** + Lookup a PTR record for a given IP address. + + @param base the evdns_base to which to apply this operation + @param in an IPv4 address + @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query. + @param callback a callback function to invoke when the request is completed + @param ptr an argument to pass to the callback function + @return an evdns_request object if successful, or NULL if an error occurred. + @see evdns_resolve_reverse_ipv6(), evdns_cancel_request() + */ +EVENT2_EXPORT_SYMBOL +struct evdns_request *evdns_base_resolve_reverse(struct evdns_base *base, const struct in_addr *in, int flags, evdns_callback_type callback, void *ptr); + + +/** + Lookup a PTR record for a given IPv6 address. + + @param base the evdns_base to which to apply this operation + @param in an IPv6 address + @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query. + @param callback a callback function to invoke when the request is completed + @param ptr an argument to pass to the callback function + @return an evdns_request object if successful, or NULL if an error occurred. + @see evdns_resolve_reverse_ipv6(), evdns_cancel_request() + */ +EVENT2_EXPORT_SYMBOL +struct evdns_request *evdns_base_resolve_reverse_ipv6(struct evdns_base *base, const struct in6_addr *in, int flags, evdns_callback_type callback, void *ptr); + +/** + Cancels a pending DNS resolution request. + + @param base the evdns_base that was used to make the request + @param req the evdns_request that was returned by calling a resolve function + @see evdns_base_resolve_ipv4(), evdns_base_resolve_ipv6, evdns_base_resolve_reverse +*/ +EVENT2_EXPORT_SYMBOL +void evdns_cancel_request(struct evdns_base *base, struct evdns_request *req); + +/** + Set the value of a configuration option. + + The currently available configuration options are: + + ndots, timeout, max-timeouts, max-inflight, attempts, randomize-case, + bind-to, initial-probe-timeout, getaddrinfo-allow-skew. + + In versions before Libevent 2.0.3-alpha, the option name needed to end with + a colon. + + @param base the evdns_base to which to apply this operation + @param option the name of the configuration option to be modified + @param val the value to be set + @return 0 if successful, or -1 if an error occurred + */ +EVENT2_EXPORT_SYMBOL +int evdns_base_set_option(struct evdns_base *base, const char *option, const char *val); + + +/** + Parse a resolv.conf file. + + The 'flags' parameter determines what information is parsed from the + resolv.conf file. See the man page for resolv.conf for the format of this + file. + + The following directives are not parsed from the file: sortlist, rotate, + no-check-names, inet6, debug. + + If this function encounters an error, the possible return values are: 1 = + failed to open file, 2 = failed to stat file, 3 = file too large, 4 = out of + memory, 5 = short read from file, 6 = no nameservers listed in the file + + @param base the evdns_base to which to apply this operation + @param flags any of DNS_OPTION_NAMESERVERS|DNS_OPTION_SEARCH|DNS_OPTION_MISC| + DNS_OPTION_HOSTSFILE|DNS_OPTIONS_ALL + @param filename the path to the resolv.conf file + @return 0 if successful, or various positive error codes if an error + occurred (see above) + @see resolv.conf(3), evdns_config_windows_nameservers() + */ +EVENT2_EXPORT_SYMBOL +int evdns_base_resolv_conf_parse(struct evdns_base *base, int flags, const char *const filename); + +/** + Load an /etc/hosts-style file from 'hosts_fname' into 'base'. + + If hosts_fname is NULL, add minimal entries for localhost, and nothing + else. + + Note that only evdns_getaddrinfo uses the /etc/hosts entries. + + This function does not replace previously loaded hosts entries; to do that, + call evdns_base_clear_host_addresses first. + + Return 0 on success, negative on failure. +*/ +EVENT2_EXPORT_SYMBOL +int evdns_base_load_hosts(struct evdns_base *base, const char *hosts_fname); + +/** + Obtain nameserver information using the Windows API. + + Attempt to configure a set of nameservers based on platform settings on + a win32 host. Preferentially tries to use GetNetworkParams; if that fails, + looks in the registry. + + @return 0 if successful, or -1 if an error occurred + @see evdns_resolv_conf_parse() + */ +#ifdef _WIN32 +EVENT2_EXPORT_SYMBOL +int evdns_base_config_windows_nameservers(struct evdns_base *); +#define EVDNS_BASE_CONFIG_WINDOWS_NAMESERVERS_IMPLEMENTED +#endif + + +/** + Clear the list of search domains. + */ +EVENT2_EXPORT_SYMBOL +void evdns_base_search_clear(struct evdns_base *base); + + +/** + Add a domain to the list of search domains + + @param domain the domain to be added to the search list + */ +EVENT2_EXPORT_SYMBOL +void evdns_base_search_add(struct evdns_base *base, const char *domain); + + +/** + Set the 'ndots' parameter for searches. + + Sets the number of dots which, when found in a name, causes + the first query to be without any search domain. + + @param ndots the new ndots parameter + */ +EVENT2_EXPORT_SYMBOL +void evdns_base_search_ndots_set(struct evdns_base *base, const int ndots); + +/** + A callback that is invoked when a log message is generated + + @param is_warning indicates if the log message is a 'warning' + @param msg the content of the log message + */ +typedef void (*evdns_debug_log_fn_type)(int is_warning, const char *msg); + + +/** + Set the callback function to handle DNS log messages. If this + callback is not set, evdns log messages are handled with the regular + Libevent logging system. + + @param fn the callback to be invoked when a log message is generated + */ +EVENT2_EXPORT_SYMBOL +void evdns_set_log_fn(evdns_debug_log_fn_type fn); + +/** + Set a callback that will be invoked to generate transaction IDs. By + default, we pick transaction IDs based on the current clock time, which + is bad for security. + + @param fn the new callback, or NULL to use the default. + + NOTE: This function has no effect in Libevent 2.0.4-alpha and later, + since Libevent now provides its own secure RNG. + */ +EVENT2_EXPORT_SYMBOL +void evdns_set_transaction_id_fn(ev_uint16_t (*fn)(void)); + +/** + Set a callback used to generate random bytes. By default, we use + the same function as passed to evdns_set_transaction_id_fn to generate + bytes two at a time. If a function is provided here, it's also used + to generate transaction IDs. + + NOTE: This function has no effect in Libevent 2.0.4-alpha and later, + since Libevent now provides its own secure RNG. +*/ +EVENT2_EXPORT_SYMBOL +void evdns_set_random_bytes_fn(void (*fn)(char *, size_t)); + +/* + * Functions used to implement a DNS server. + */ + +struct evdns_server_request; +struct evdns_server_question; + +/** + A callback to implement a DNS server. The callback function receives a DNS + request. It should then optionally add a number of answers to the reply + using the evdns_server_request_add_*_reply functions, before calling either + evdns_server_request_respond to send the reply back, or + evdns_server_request_drop to decline to answer the request. + + @param req A newly received request + @param user_data A pointer that was passed to + evdns_add_server_port_with_base(). + */ +typedef void (*evdns_request_callback_fn_type)(struct evdns_server_request *, void *); +#define EVDNS_ANSWER_SECTION 0 +#define EVDNS_AUTHORITY_SECTION 1 +#define EVDNS_ADDITIONAL_SECTION 2 + +#define EVDNS_TYPE_A 1 +#define EVDNS_TYPE_NS 2 +#define EVDNS_TYPE_CNAME 5 +#define EVDNS_TYPE_SOA 6 +#define EVDNS_TYPE_PTR 12 +#define EVDNS_TYPE_MX 15 +#define EVDNS_TYPE_TXT 16 +#define EVDNS_TYPE_AAAA 28 + +#define EVDNS_QTYPE_AXFR 252 +#define EVDNS_QTYPE_ALL 255 + +#define EVDNS_CLASS_INET 1 + +/* flags that can be set in answers; as part of the err parameter */ +#define EVDNS_FLAGS_AA 0x400 +#define EVDNS_FLAGS_RD 0x080 + +/** Create a new DNS server port. + + @param base The event base to handle events for the server port. + @param socket A UDP socket to accept DNS requests. + @param flags Always 0 for now. + @param callback A function to invoke whenever we get a DNS request + on the socket. + @param user_data Data to pass to the callback. + @return an evdns_server_port structure for this server port. + */ +EVENT2_EXPORT_SYMBOL +struct evdns_server_port *evdns_add_server_port_with_base(struct event_base *base, evutil_socket_t socket, int flags, evdns_request_callback_fn_type callback, void *user_data); +/** Close down a DNS server port, and free associated structures. */ +EVENT2_EXPORT_SYMBOL +void evdns_close_server_port(struct evdns_server_port *port); + +/** Sets some flags in a reply we're building. + Allows setting of the AA or RD flags + */ +EVENT2_EXPORT_SYMBOL +void evdns_server_request_set_flags(struct evdns_server_request *req, int flags); + +/* Functions to add an answer to an in-progress DNS reply. + */ +EVENT2_EXPORT_SYMBOL +int evdns_server_request_add_reply(struct evdns_server_request *req, int section, const char *name, int type, int dns_class, int ttl, int datalen, int is_name, const char *data); +EVENT2_EXPORT_SYMBOL +int evdns_server_request_add_a_reply(struct evdns_server_request *req, const char *name, int n, const void *addrs, int ttl); +EVENT2_EXPORT_SYMBOL +int evdns_server_request_add_aaaa_reply(struct evdns_server_request *req, const char *name, int n, const void *addrs, int ttl); +EVENT2_EXPORT_SYMBOL +int evdns_server_request_add_ptr_reply(struct evdns_server_request *req, struct in_addr *in, const char *inaddr_name, const char *hostname, int ttl); +EVENT2_EXPORT_SYMBOL +int evdns_server_request_add_cname_reply(struct evdns_server_request *req, const char *name, const char *cname, int ttl); + +/** + Send back a response to a DNS request, and free the request structure. +*/ +EVENT2_EXPORT_SYMBOL +int evdns_server_request_respond(struct evdns_server_request *req, int err); +/** + Free a DNS request without sending back a reply. +*/ +EVENT2_EXPORT_SYMBOL +int evdns_server_request_drop(struct evdns_server_request *req); +struct sockaddr; +/** + Get the address that made a DNS request. + */ +EVENT2_EXPORT_SYMBOL +int evdns_server_request_get_requesting_addr(struct evdns_server_request *req, struct sockaddr *sa, int addr_len); + +/** Callback for evdns_getaddrinfo. */ +typedef void (*evdns_getaddrinfo_cb)(int result, struct evutil_addrinfo *res, void *arg); + +struct evdns_base; +struct evdns_getaddrinfo_request; +/** Make a non-blocking getaddrinfo request using the dns_base in 'dns_base'. + * + * If we can answer the request immediately (with an error or not!), then we + * invoke cb immediately and return NULL. Otherwise we return + * an evdns_getaddrinfo_request and invoke cb later. + * + * When the callback is invoked, we pass as its first argument the error code + * that getaddrinfo would return (or 0 for no error). As its second argument, + * we pass the evutil_addrinfo structures we found (or NULL on error). We + * pass 'arg' as the third argument. + * + * Limitations: + * + * - The AI_V4MAPPED and AI_ALL flags are not currently implemented. + * - For ai_socktype, we only handle SOCKTYPE_STREAM, SOCKTYPE_UDP, and 0. + * - For ai_protocol, we only handle IPPROTO_TCP, IPPROTO_UDP, and 0. + */ +EVENT2_EXPORT_SYMBOL +struct evdns_getaddrinfo_request *evdns_getaddrinfo( + struct evdns_base *dns_base, + const char *nodename, const char *servname, + const struct evutil_addrinfo *hints_in, + evdns_getaddrinfo_cb cb, void *arg); + +/* Cancel an in-progress evdns_getaddrinfo. This MUST NOT be called after the + * getaddrinfo's callback has been invoked. The resolves will be canceled, + * and the callback will be invoked with the error EVUTIL_EAI_CANCEL. */ +EVENT2_EXPORT_SYMBOL +void evdns_getaddrinfo_cancel(struct evdns_getaddrinfo_request *req); + +/** + Retrieve the address of the 'idx'th configured nameserver. + + @param base The evdns_base to examine. + @param idx The index of the nameserver to get the address of. + @param sa A location to receive the server's address. + @param len The number of bytes available at sa. + + @return the number of bytes written into sa on success. On failure, returns + -1 if idx is greater than the number of configured nameservers, or a + value greater than 'len' if len was not high enough. + */ +EVENT2_EXPORT_SYMBOL +int evdns_base_get_nameserver_addr(struct evdns_base *base, int idx, + struct sockaddr *sa, ev_socklen_t len); + +#ifdef __cplusplus +} +#endif + +#endif /* !EVENT2_DNS_H_INCLUDED_ */ diff --git a/src/include/event2/dns_compat.h b/src/include/event2/dns_compat.h new file mode 100644 index 0000000..965fd65 --- /dev/null +++ b/src/include/event2/dns_compat.h @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2006-2007 Niels Provos <[email protected]> + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EVENT2_DNS_COMPAT_H_INCLUDED_ +#define EVENT2_DNS_COMPAT_H_INCLUDED_ + +/** @file event2/dns_compat.h + + Potentially non-threadsafe versions of the functions in dns.h: provided + only for backwards compatibility. + + + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <event2/event-config.h> +#ifdef EVENT__HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef EVENT__HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + +/* For int types. */ +#include <event2/util.h> + +/** + Initialize the asynchronous DNS library. + + This function initializes support for non-blocking name resolution by + calling evdns_resolv_conf_parse() on UNIX and + evdns_config_windows_nameservers() on Windows. + + @deprecated This function is deprecated because it always uses the current + event base, and is easily confused by multiple calls to event_init(), and + so is not safe for multithreaded use. Additionally, it allocates a global + structure that only one thread can use. The replacement is + evdns_base_new(). + + @return 0 if successful, or -1 if an error occurred + @see evdns_shutdown() + */ +int evdns_init(void); + +struct evdns_base; +/** + Return the global evdns_base created by event_init() and used by the other + deprecated functions. + + @deprecated This function is deprecated because use of the global + evdns_base is error-prone. + */ +struct evdns_base *evdns_get_global_base(void); + +/** + Shut down the asynchronous DNS resolver and terminate all active requests. + + If the 'fail_requests' option is enabled, all active requests will return + an empty result with the error flag set to DNS_ERR_SHUTDOWN. Otherwise, + the requests will be silently discarded. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_shutdown(). + + @param fail_requests if zero, active requests will be aborted; if non-zero, + active requests will return DNS_ERR_SHUTDOWN. + @see evdns_init() + */ +void evdns_shutdown(int fail_requests); + +/** + Add a nameserver. + + The address should be an IPv4 address in network byte order. + The type of address is chosen so that it matches in_addr.s_addr. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_nameserver_add(). + + @param address an IP address in network byte order + @return 0 if successful, or -1 if an error occurred + @see evdns_nameserver_ip_add() + */ +int evdns_nameserver_add(unsigned long int address); + +/** + Get the number of configured nameservers. + + This returns the number of configured nameservers (not necessarily the + number of running nameservers). This is useful for double-checking + whether our calls to the various nameserver configuration functions + have been successful. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_count_nameservers(). + + @return the number of configured nameservers + @see evdns_nameserver_add() + */ +int evdns_count_nameservers(void); + +/** + Remove all configured nameservers, and suspend all pending resolves. + + Resolves will not necessarily be re-attempted until evdns_resume() is called. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_clear_nameservers_and_suspend(). + + @return 0 if successful, or -1 if an error occurred + @see evdns_resume() + */ +int evdns_clear_nameservers_and_suspend(void); + +/** + Resume normal operation and continue any suspended resolve requests. + + Re-attempt resolves left in limbo after an earlier call to + evdns_clear_nameservers_and_suspend(). + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_resume(). + + @return 0 if successful, or -1 if an error occurred + @see evdns_clear_nameservers_and_suspend() + */ +int evdns_resume(void); + +/** + Add a nameserver. + + This wraps the evdns_nameserver_add() function by parsing a string as an IP + address and adds it as a nameserver. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_nameserver_ip_add(). + + @return 0 if successful, or -1 if an error occurred + @see evdns_nameserver_add() + */ +int evdns_nameserver_ip_add(const char *ip_as_string); + +/** + Lookup an A record for a given name. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_resolve_ipv4(). + + @param name a DNS hostname + @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query. + @param callback a callback function to invoke when the request is completed + @param ptr an argument to pass to the callback function + @return 0 if successful, or -1 if an error occurred + @see evdns_resolve_ipv6(), evdns_resolve_reverse(), evdns_resolve_reverse_ipv6() + */ +int evdns_resolve_ipv4(const char *name, int flags, evdns_callback_type callback, void *ptr); + +/** + Lookup an AAAA record for a given name. + + @param name a DNS hostname + @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query. + @param callback a callback function to invoke when the request is completed + @param ptr an argument to pass to the callback function + @return 0 if successful, or -1 if an error occurred + @see evdns_resolve_ipv4(), evdns_resolve_reverse(), evdns_resolve_reverse_ipv6() + */ +int evdns_resolve_ipv6(const char *name, int flags, evdns_callback_type callback, void *ptr); + +struct in_addr; +struct in6_addr; + +/** + Lookup a PTR record for a given IP address. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_resolve_reverse(). + + @param in an IPv4 address + @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query. + @param callback a callback function to invoke when the request is completed + @param ptr an argument to pass to the callback function + @return 0 if successful, or -1 if an error occurred + @see evdns_resolve_reverse_ipv6() + */ +int evdns_resolve_reverse(const struct in_addr *in, int flags, evdns_callback_type callback, void *ptr); + +/** + Lookup a PTR record for a given IPv6 address. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_resolve_reverse_ipv6(). + + @param in an IPv6 address + @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query. + @param callback a callback function to invoke when the request is completed + @param ptr an argument to pass to the callback function + @return 0 if successful, or -1 if an error occurred + @see evdns_resolve_reverse_ipv6() + */ +int evdns_resolve_reverse_ipv6(const struct in6_addr *in, int flags, evdns_callback_type callback, void *ptr); + +/** + Set the value of a configuration option. + + The currently available configuration options are: + + ndots, timeout, max-timeouts, max-inflight, and attempts + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_set_option(). + + @param option the name of the configuration option to be modified + @param val the value to be set + @param flags Ignored. + @return 0 if successful, or -1 if an error occurred + */ +int evdns_set_option(const char *option, const char *val, int flags); + +/** + Parse a resolv.conf file. + + The 'flags' parameter determines what information is parsed from the + resolv.conf file. See the man page for resolv.conf for the format of this + file. + + The following directives are not parsed from the file: sortlist, rotate, + no-check-names, inet6, debug. + + If this function encounters an error, the possible return values are: 1 = + failed to open file, 2 = failed to stat file, 3 = file too large, 4 = out of + memory, 5 = short read from file, 6 = no nameservers listed in the file + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_resolv_conf_parse(). + + @param flags any of DNS_OPTION_NAMESERVERS|DNS_OPTION_SEARCH|DNS_OPTION_MISC| + DNS_OPTIONS_ALL + @param filename the path to the resolv.conf file + @return 0 if successful, or various positive error codes if an error + occurred (see above) + @see resolv.conf(3), evdns_config_windows_nameservers() + */ +int evdns_resolv_conf_parse(int flags, const char *const filename); + +/** + Clear the list of search domains. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_search_clear(). + */ +void evdns_search_clear(void); + +/** + Add a domain to the list of search domains + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_search_add(). + + @param domain the domain to be added to the search list + */ +void evdns_search_add(const char *domain); + +/** + Set the 'ndots' parameter for searches. + + Sets the number of dots which, when found in a name, causes + the first query to be without any search domain. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_search_ndots_set(). + + @param ndots the new ndots parameter + */ +void evdns_search_ndots_set(const int ndots); + +/** + As evdns_server_new_with_base. + + @deprecated This function is deprecated because it does not allow the + caller to specify which even_base it uses. The recommended + function is evdns_add_server_port_with_base(). + +*/ +struct evdns_server_port *evdns_add_server_port(evutil_socket_t socket, int flags, evdns_request_callback_fn_type callback, void *user_data); + +#ifdef _WIN32 +int evdns_config_windows_nameservers(void); +#define EVDNS_CONFIG_WINDOWS_NAMESERVERS_IMPLEMENTED +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_EVENT_COMPAT_H_INCLUDED_ */ diff --git a/src/include/event2/dns_struct.h b/src/include/event2/dns_struct.h new file mode 100644 index 0000000..593a8a7 --- /dev/null +++ b/src/include/event2/dns_struct.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2000-2007 Niels Provos <[email protected]> + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EVENT2_DNS_STRUCT_H_INCLUDED_ +#define EVENT2_DNS_STRUCT_H_INCLUDED_ + +/** @file event2/dns_struct.h + + Data structures for dns. Using these structures may hurt forward + compatibility with later versions of Libevent: be careful! + + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <event2/event-config.h> +#ifdef EVENT__HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef EVENT__HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + +/* For int types. */ +#include <event2/util.h> + +/* + * Structures used to implement a DNS server. + */ + +struct evdns_server_request { + int flags; + int nquestions; + struct evdns_server_question **questions; +}; +struct evdns_server_question { + int type; +#ifdef __cplusplus + int dns_question_class; +#else + /* You should refer to this field as "dns_question_class". The + * name "class" works in C for backward compatibility, and will be + * removed in a future version. (1.5 or later). */ + int class; +#define dns_question_class class +#endif + char name[1]; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_DNS_STRUCT_H_INCLUDED_ */ + diff --git a/src/include/event2/event-config.h b/src/include/event2/event-config.h new file mode 100644 index 0000000..36cd9a6 --- /dev/null +++ b/src/include/event2/event-config.h @@ -0,0 +1,545 @@ +/* event2/event-config.h + * + * This file was generated by autoconf when libevent was built, and post- + * processed by Libevent so that its macros would have a uniform prefix. + * + * DO NOT EDIT THIS FILE. + * + * Do not rely on macros in this file existing in later versions. + */ + +#ifndef EVENT2_EVENT_CONFIG_H_INCLUDED_ +#define EVENT2_EVENT_CONFIG_H_INCLUDED_ + +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if libevent should build without support for a debug mode */ +/* #undef EVENT__DISABLE_DEBUG_MODE */ + +/* Define if libevent should not allow replacing the mm functions */ +/* #undef EVENT__DISABLE_MM_REPLACEMENT */ + +/* Define if libevent should not be compiled with thread support */ +/* #undef EVENT__DISABLE_THREAD_SUPPORT */ + +/* Define to 1 if you have the `accept4' function. */ +#define EVENT__HAVE_ACCEPT4 1 + +/* Define to 1 if you have the `arc4random' function. */ +/* #undef EVENT__HAVE_ARC4RANDOM */ + +/* Define to 1 if you have the `arc4random_buf' function. */ +/* #undef EVENT__HAVE_ARC4RANDOM_BUF */ + +/* Define to 1 if you have the <arpa/inet.h> header file. */ +#define EVENT__HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the `clock_gettime' function. */ +#define EVENT__HAVE_CLOCK_GETTIME 1 + +/* Define to 1 if you have the declaration of `CTL_KERN', and to 0 if you + don't. */ +#define EVENT__HAVE_DECL_CTL_KERN 1 + +/* Define to 1 if you have the declaration of `KERN_ARND', and to 0 if you + don't. */ +#define EVENT__HAVE_DECL_KERN_ARND 0 + +/* Define to 1 if you have the declaration of `KERN_RANDOM', and to 0 if you + don't. */ +#define EVENT__HAVE_DECL_KERN_RANDOM 1 + +/* Define to 1 if you have the declaration of `RANDOM_UUID', and to 0 if you + don't. */ +#define EVENT__HAVE_DECL_RANDOM_UUID 1 + +/* Define if /dev/poll is available */ +/* #undef EVENT__HAVE_DEVPOLL */ + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#define EVENT__HAVE_DLFCN_H 1 + +/* Define if your system supports the epoll system calls */ +#define EVENT__HAVE_EPOLL 1 + +/* Define to 1 if you have the `epoll_create1' function. */ +#define EVENT__HAVE_EPOLL_CREATE1 1 + +/* Define to 1 if you have the `epoll_ctl' function. */ +#define EVENT__HAVE_EPOLL_CTL 1 + +/* Define to 1 if you have the <errno.h> header file. */ +#define EVENT__HAVE_ERRNO_H 1 + +/* Define to 1 if you have ERR_remove_thread_stat(). */ +#define EVENT__HAVE_ERR_REMOVE_THREAD_STATE 1 + +/* Define to 1 if you have the `eventfd' function. */ +#define EVENT__HAVE_EVENTFD 1 + +/* Define if your system supports event ports */ +/* #undef EVENT__HAVE_EVENT_PORTS */ + +/* Define to 1 if you have the `fcntl' function. */ +#define EVENT__HAVE_FCNTL 1 + +/* Define to 1 if you have the <fcntl.h> header file. */ +#define EVENT__HAVE_FCNTL_H 1 + +/* Define to 1 if the system has the type `fd_mask'. */ +#define EVENT__HAVE_FD_MASK 1 + +/* Do we have getaddrinfo()? */ +#define EVENT__HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the `getegid' function. */ +#define EVENT__HAVE_GETEGID 1 + +/* Define to 1 if you have the `geteuid' function. */ +#define EVENT__HAVE_GETEUID 1 + +/* Define this if you have any gethostbyname_r() */ +/* #undef EVENT__HAVE_GETHOSTBYNAME_R */ + +/* Define this if gethostbyname_r takes 3 arguments */ +/* #undef EVENT__HAVE_GETHOSTBYNAME_R_3_ARG */ + +/* Define this if gethostbyname_r takes 5 arguments */ +/* #undef EVENT__HAVE_GETHOSTBYNAME_R_5_ARG */ + +/* Define this if gethostbyname_r takes 6 arguments */ +/* #undef EVENT__HAVE_GETHOSTBYNAME_R_6_ARG */ + +/* Define to 1 if you have the `getifaddrs' function. */ +#define EVENT__HAVE_GETIFADDRS 1 + +/* Define to 1 if you have the `getnameinfo' function. */ +#define EVENT__HAVE_GETNAMEINFO 1 + +/* Define to 1 if you have the `getprotobynumber' function. */ +#define EVENT__HAVE_GETPROTOBYNUMBER 1 + +/* Define to 1 if you have the `getservbyname' function. */ +#define EVENT__HAVE_GETSERVBYNAME 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#define EVENT__HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the <ifaddrs.h> header file. */ +#define EVENT__HAVE_IFADDRS_H 1 + +/* Define to 1 if you have the `inet_ntop' function. */ +#define EVENT__HAVE_INET_NTOP 1 + +/* Define to 1 if you have the `inet_pton' function. */ +#define EVENT__HAVE_INET_PTON 1 + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define EVENT__HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `issetugid' function. */ +/* #undef EVENT__HAVE_ISSETUGID */ + +/* Define to 1 if you have the `kqueue' function. */ +/* #undef EVENT__HAVE_KQUEUE */ + +/* Define if the system has zlib */ +/* #undef EVENT__HAVE_LIBZ */ + +/* Define to 1 if you have the `mach_absolute_time' function. */ +/* #undef EVENT__HAVE_MACH_ABSOLUTE_TIME */ + +/* Define to 1 if you have the <mach/mach_time.h> header file. */ +/* #undef EVENT__HAVE_MACH_MACH_TIME_H */ + +/* Define to 1 if you have the <memory.h> header file. */ +#define EVENT__HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mmap' function. */ +#define EVENT__HAVE_MMAP 1 + +/* Define to 1 if you have the `nanosleep' function. */ +#define EVENT__HAVE_NANOSLEEP 1 + +/* Define to 1 if you have the <netdb.h> header file. */ +#define EVENT__HAVE_NETDB_H 1 + +/* Define to 1 if you have the <netinet/in6.h> header file. */ +/* #undef EVENT__HAVE_NETINET_IN6_H */ + +/* Define to 1 if you have the <netinet/in.h> header file. */ +#define EVENT__HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the <netinet/tcp.h> header file. */ +#define EVENT__HAVE_NETINET_TCP_H 1 + +/* Define if the system has openssl */ +#define EVENT__HAVE_OPENSSL 1 + +/* Define to 1 if you have the `pipe' function. */ +#define EVENT__HAVE_PIPE 1 + +/* Define to 1 if you have the `pipe2' function. */ +#define EVENT__HAVE_PIPE2 1 + +/* Define to 1 if you have the `poll' function. */ +#define EVENT__HAVE_POLL 1 + +/* Define to 1 if you have the <poll.h> header file. */ +#define EVENT__HAVE_POLL_H 1 + +/* Define to 1 if you have the `port_create' function. */ +/* #undef EVENT__HAVE_PORT_CREATE */ + +/* Define to 1 if you have the <port.h> header file. */ +/* #undef EVENT__HAVE_PORT_H */ + +/* Define if you have POSIX threads libraries and header files. */ +/* #undef EVENT__HAVE_PTHREAD */ + +/* Define if we have pthreads on this system */ +#define EVENT__HAVE_PTHREADS 1 + +/* Define to 1 if you have the `putenv' function. */ +#define EVENT__HAVE_PUTENV 1 + +/* Define to 1 if the system has the type `sa_family_t'. */ +#define EVENT__HAVE_SA_FAMILY_T 1 + +/* Define to 1 if you have the `select' function. */ +#define EVENT__HAVE_SELECT 1 + +/* Define to 1 if you have the `sendfile' function. */ +#define EVENT__HAVE_SENDFILE 1 + +/* Define to 1 if you have the `setenv' function. */ +#define EVENT__HAVE_SETENV 1 + +/* Define if F_SETFD is defined in <fcntl.h> */ +#define EVENT__HAVE_SETFD 1 + +/* Define to 1 if you have the `setrlimit' function. */ +#define EVENT__HAVE_SETRLIMIT 1 + +/* Define to 1 if you have the `sigaction' function. */ +#define EVENT__HAVE_SIGACTION 1 + +/* Define to 1 if you have the `signal' function. */ +#define EVENT__HAVE_SIGNAL 1 + +/* Define to 1 if you have the `splice' function. */ +#define EVENT__HAVE_SPLICE 1 + +/* Define to 1 if you have the <stdarg.h> header file. */ +#define EVENT__HAVE_STDARG_H 1 + +/* Define to 1 if you have the <stddef.h> header file. */ +#define EVENT__HAVE_STDDEF_H 1 + +/* Define to 1 if you have the <stdint.h> header file. */ +#define EVENT__HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define EVENT__HAVE_STDLIB_H 1 + +/* Define to 1 if you have the <strings.h> header file. */ +#define EVENT__HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> header file. */ +#define EVENT__HAVE_STRING_H 1 + +/* Define to 1 if you have the `strlcpy' function. */ +/* #undef EVENT__HAVE_STRLCPY */ + +/* Define to 1 if you have the `strsep' function. */ +#define EVENT__HAVE_STRSEP 1 + +/* Define to 1 if you have the `strtok_r' function. */ +#define EVENT__HAVE_STRTOK_R 1 + +/* Define to 1 if you have the `strtoll' function. */ +#define EVENT__HAVE_STRTOLL 1 + +/* Define to 1 if the system has the type `struct addrinfo'. */ +#define EVENT__HAVE_STRUCT_ADDRINFO 1 + +/* Define to 1 if the system has the type `struct in6_addr'. */ +#define EVENT__HAVE_STRUCT_IN6_ADDR 1 + +/* Define to 1 if `s6_addr16' is a member of `struct in6_addr'. */ +#define EVENT__HAVE_STRUCT_IN6_ADDR_S6_ADDR16 1 + +/* Define to 1 if `s6_addr32' is a member of `struct in6_addr'. */ +#define EVENT__HAVE_STRUCT_IN6_ADDR_S6_ADDR32 1 + +/* Define to 1 if the system has the type `struct sockaddr_in6'. */ +#define EVENT__HAVE_STRUCT_SOCKADDR_IN6 1 + +/* Define to 1 if `sin6_len' is a member of `struct sockaddr_in6'. */ +/* #undef EVENT__HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN */ + +/* Define to 1 if `sin_len' is a member of `struct sockaddr_in'. */ +/* #undef EVENT__HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ + +/* Define to 1 if the system has the type `struct sockaddr_storage'. */ +#define EVENT__HAVE_STRUCT_SOCKADDR_STORAGE 1 + +/* Define to 1 if `ss_family' is a member of `struct sockaddr_storage'. */ +#define EVENT__HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY 1 + +/* Define to 1 if `__ss_family' is a member of `struct sockaddr_storage'. */ +/* #undef EVENT__HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY */ + +/* Define to 1 if the system has the type `struct so_linger'. */ +/* #undef EVENT__HAVE_STRUCT_SO_LINGER */ + +/* Define to 1 if you have the `sysctl' function. */ +#define EVENT__HAVE_SYSCTL 1 + +/* Define to 1 if you have the <sys/devpoll.h> header file. */ +/* #undef EVENT__HAVE_SYS_DEVPOLL_H */ + +/* Define to 1 if you have the <sys/epoll.h> header file. */ +#define EVENT__HAVE_SYS_EPOLL_H 1 + +/* Define to 1 if you have the <sys/eventfd.h> header file. */ +#define EVENT__HAVE_SYS_EVENTFD_H 1 + +/* Define to 1 if you have the <sys/event.h> header file. */ +/* #undef EVENT__HAVE_SYS_EVENT_H */ + +/* Define to 1 if you have the <sys/ioctl.h> header file. */ +#define EVENT__HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the <sys/mman.h> header file. */ +#define EVENT__HAVE_SYS_MMAN_H 1 + +/* Define to 1 if you have the <sys/param.h> header file. */ +#define EVENT__HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the <sys/queue.h> header file. */ +#define EVENT__HAVE_SYS_QUEUE_H 1 + +/* Define to 1 if you have the <sys/resource.h> header file. */ +#define EVENT__HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the <sys/select.h> header file. */ +#define EVENT__HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the <sys/sendfile.h> header file. */ +#define EVENT__HAVE_SYS_SENDFILE_H 1 + +/* Define to 1 if you have the <sys/socket.h> header file. */ +#define EVENT__HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define EVENT__HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/sysctl.h> header file. */ +#define EVENT__HAVE_SYS_SYSCTL_H 1 + +/* Define to 1 if you have the <sys/timerfd.h> header file. */ +#define EVENT__HAVE_SYS_TIMERFD_H 1 + +/* Define to 1 if you have the <sys/time.h> header file. */ +#define EVENT__HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define EVENT__HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the <sys/uio.h> header file. */ +#define EVENT__HAVE_SYS_UIO_H 1 + +/* Define to 1 if you have the <sys/wait.h> header file. */ +#define EVENT__HAVE_SYS_WAIT_H 1 + +/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */ +#define EVENT__HAVE_TAILQFOREACH 1 + +/* Define if timeradd is defined in <sys/time.h> */ +#define EVENT__HAVE_TIMERADD 1 + +/* Define if timerclear is defined in <sys/time.h> */ +#define EVENT__HAVE_TIMERCLEAR 1 + +/* Define if timercmp is defined in <sys/time.h> */ +#define EVENT__HAVE_TIMERCMP 1 + +/* Define to 1 if you have the `timerfd_create' function. */ +#define EVENT__HAVE_TIMERFD_CREATE 1 + +/* Define if timerisset is defined in <sys/time.h> */ +#define EVENT__HAVE_TIMERISSET 1 + +/* Define to 1 if the system has the type `uint16_t'. */ +#define EVENT__HAVE_UINT16_T 1 + +/* Define to 1 if the system has the type `uint32_t'. */ +#define EVENT__HAVE_UINT32_T 1 + +/* Define to 1 if the system has the type `uint64_t'. */ +#define EVENT__HAVE_UINT64_T 1 + +/* Define to 1 if the system has the type `uint8_t'. */ +#define EVENT__HAVE_UINT8_T 1 + +/* Define to 1 if the system has the type `uintptr_t'. */ +#define EVENT__HAVE_UINTPTR_T 1 + +/* Define to 1 if you have the `umask' function. */ +#define EVENT__HAVE_UMASK 1 + +/* Define to 1 if you have the <unistd.h> header file. */ +#define EVENT__HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `unsetenv' function. */ +#define EVENT__HAVE_UNSETENV 1 + +/* Define to 1 if you have the `usleep' function. */ +#define EVENT__HAVE_USLEEP 1 + +/* Define to 1 if you have the `vasprintf' function. */ +#define EVENT__HAVE_VASPRINTF 1 + +/* Define if waitpid() supports WNOWAIT */ +/* #undef EVENT__HAVE_WAITPID_WITH_WNOWAIT */ + +/* Define if kqueue works correctly with pipes */ +/* #undef EVENT__HAVE_WORKING_KQUEUE */ + +/* Define to 1 if you have the <zlib.h> header file. */ +/* #undef EVENT__HAVE_ZLIB_H */ + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#define EVENT__LT_OBJDIR ".libs/" + +/* Numeric representation of the version */ +#define EVENT__NUMERIC_VERSION 0x02010800 + +/* Name of package */ +#define EVENT__PACKAGE "libevent" + +/* Define to the address where bug reports for this package should be sent. */ +#define EVENT__PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define EVENT__PACKAGE_NAME "libevent" + +/* Define to the full name and version of this package. */ +#define EVENT__PACKAGE_STRING "libevent 2.1.8-stable" + +/* Define to the one symbol short name of this package. */ +#define EVENT__PACKAGE_TARNAME "libevent" + +/* Define to the home page for this package. */ +#define EVENT__PACKAGE_URL "" + +/* Define to the version of this package. */ +#define EVENT__PACKAGE_VERSION "2.1.8-stable" + +/* Define to necessary symbol if this constant uses a non-standard name on + your system. */ +/* #undef EVENT__PTHREAD_CREATE_JOINABLE */ + +/* The size of `int', as computed by sizeof. */ +#define EVENT__SIZEOF_INT 4 + +/* The size of `long', as computed by sizeof. */ +#define EVENT__SIZEOF_LONG 8 + +/* The size of `long long', as computed by sizeof. */ +#define EVENT__SIZEOF_LONG_LONG 8 + +/* The size of `off_t', as computed by sizeof. */ +#define EVENT__SIZEOF_OFF_T 8 + +/* The size of `pthread_t', as computed by sizeof. */ +#define EVENT__SIZEOF_PTHREAD_T 8 + +/* The size of `short', as computed by sizeof. */ +#define EVENT__SIZEOF_SHORT 2 + +/* The size of `size_t', as computed by sizeof. */ +#define EVENT__SIZEOF_SIZE_T 8 + +/* The size of `void *', as computed by sizeof. */ +#define EVENT__SIZEOF_VOID_P 8 + +/* Define to 1 if you have the ANSI C header files. */ +#define EVENT__STDC_HEADERS 1 + +/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ +#define EVENT__TIME_WITH_SYS_TIME 1 + +/* Enable extensions on AIX 3, Interix. */ +#ifndef EVENT___ALL_SOURCE +# define EVENT___ALL_SOURCE 1 +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef EVENT___GNU_SOURCE +# define EVENT___GNU_SOURCE 1 +#endif +/* Enable threading extensions on Solaris. */ +#ifndef EVENT___POSIX_PTHREAD_SEMANTICS +# define EVENT___POSIX_PTHREAD_SEMANTICS 1 +#endif +/* Enable extensions on HP NonStop. */ +#ifndef EVENT___TANDEM_SOURCE +# define EVENT___TANDEM_SOURCE 1 +#endif +/* Enable general extensions on Solaris. */ +#ifndef EVENT____EXTENSIONS__ +# define EVENT____EXTENSIONS__ 1 +#endif + + +/* Version number of package */ +#define EVENT__VERSION "2.1.8-stable" + +/* Enable large inode numbers on Mac OS X 10.5. */ +#ifndef EVENT___DARWIN_USE_64_BIT_INODE +# define EVENT___DARWIN_USE_64_BIT_INODE 1 +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef EVENT___FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef EVENT___LARGE_FILES */ + +/* Define to 1 if on MINIX. */ +/* #undef EVENT___MINIX */ + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +/* #undef EVENT___POSIX_1_SOURCE */ + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +/* #undef EVENT___POSIX_SOURCE */ + +/* Define to appropriate substitue if compiler doesnt have __func__ */ +/* #undef EVENT____func__ */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef EVENT__const */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef EVENT____cplusplus +/* #undef EVENT__inline */ +#endif + +/* Define to `int' if <sys/types.h> does not define. */ +/* #undef EVENT__pid_t */ + +/* Define to `unsigned int' if <sys/types.h> does not define. */ +/* #undef EVENT__size_t */ + +/* Define to unsigned int if you dont have it */ +/* #undef EVENT__socklen_t */ + +/* Define to `int' if <sys/types.h> does not define. */ +/* #undef EVENT__ssize_t */ + +#endif /* event2/event-config.h */ diff --git a/src/include/event2/event.h b/src/include/event2/event.h new file mode 100644 index 0000000..6e0a4f0 --- /dev/null +++ b/src/include/event2/event.h @@ -0,0 +1,1675 @@ +/* + * Copyright (c) 2000-2007 Niels Provos <[email protected]> + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EVENT2_EVENT_H_INCLUDED_ +#define EVENT2_EVENT_H_INCLUDED_ + +/** + @mainpage + + @section intro Introduction + + Libevent is an event notification library for developing scalable network + servers. The Libevent API provides a mechanism to execute a callback + function when a specific event occurs on a file descriptor or after a + timeout has been reached. Furthermore, Libevent also support callbacks due + to signals or regular timeouts. + + Libevent is meant to replace the event loop found in event driven network + servers. An application just needs to call event_base_dispatch() and then add or + remove events dynamically without having to change the event loop. + + + Currently, Libevent supports /dev/poll, kqueue(2), select(2), poll(2), + epoll(4), and evports. The internal event mechanism is completely + independent of the exposed event API, and a simple update of Libevent can + provide new functionality without having to redesign the applications. As a + result, Libevent allows for portable application development and provides + the most scalable event notification mechanism available on an operating + system. Libevent can also be used for multithreaded programs. Libevent + should compile on Linux, *BSD, Mac OS X, Solaris and, Windows. + + @section usage Standard usage + + Every program that uses Libevent must include the <event2/event.h> + header, and pass the -levent flag to the linker. (You can instead link + -levent_core if you only want the main event and buffered IO-based code, + and don't want to link any protocol code.) + + @section setup Library setup + + Before you call any other Libevent functions, you need to set up the + library. If you're going to use Libevent from multiple threads in a + multithreaded application, you need to initialize thread support -- + typically by using evthread_use_pthreads() or + evthread_use_windows_threads(). See <event2/thread.h> for more + information. + + This is also the point where you can replace Libevent's memory + management functions with event_set_mem_functions, and enable debug mode + with event_enable_debug_mode(). + + @section base Creating an event base + + Next, you need to create an event_base structure, using event_base_new() + or event_base_new_with_config(). The event_base is responsible for + keeping track of which events are "pending" (that is to say, being + watched to see if they become active) and which events are "active". + Every event is associated with a single event_base. + + @section event Event notification + + For each file descriptor that you wish to monitor, you must create an + event structure with event_new(). (You may also declare an event + structure and call event_assign() to initialize the members of the + structure.) To enable notification, you add the structure to the list + of monitored events by calling event_add(). The event structure must + remain allocated as long as it is active, so it should generally be + allocated on the heap. + + @section loop Dispatching events. + + Finally, you call event_base_dispatch() to loop and dispatch events. + You can also use event_base_loop() for more fine-grained control. + + Currently, only one thread can be dispatching a given event_base at a + time. If you want to run events in multiple threads at once, you can + either have a single event_base whose events add work to a work queue, + or you can create multiple event_base objects. + + @section bufferevent I/O Buffers + + Libevent provides a buffered I/O abstraction on top of the regular event + callbacks. This abstraction is called a bufferevent. A bufferevent + provides input and output buffers that get filled and drained + automatically. The user of a buffered event no longer deals directly + with the I/O, but instead is reading from input and writing to output + buffers. + + Once initialized via bufferevent_socket_new(), the bufferevent structure + can be used repeatedly with bufferevent_enable() and + bufferevent_disable(). Instead of reading and writing directly to a + socket, you would call bufferevent_read() and bufferevent_write(). + + When read enabled the bufferevent will try to read from the file descriptor + and call the read callback. The write callback is executed whenever the + output buffer is drained below the write low watermark, which is 0 by + default. + + See <event2/bufferevent*.h> for more information. + + @section timers Timers + + Libevent can also be used to create timers that invoke a callback after a + certain amount of time has expired. The evtimer_new() macro returns + an event struct to use as a timer. To activate the timer, call + evtimer_add(). Timers can be deactivated by calling evtimer_del(). + (These macros are thin wrappers around event_new(), event_add(), + and event_del(); you can also use those instead.) + + @section evdns Asynchronous DNS resolution + + Libevent provides an asynchronous DNS resolver that should be used instead + of the standard DNS resolver functions. See the <event2/dns.h> + functions for more detail. + + @section evhttp Event-driven HTTP servers + + Libevent provides a very simple event-driven HTTP server that can be + embedded in your program and used to service HTTP requests. + + To use this capability, you need to include the <event2/http.h> header in your + program. See that header for more information. + + @section evrpc A framework for RPC servers and clients + + Libevent provides a framework for creating RPC servers and clients. It + takes care of marshaling and unmarshaling all data structures. + + @section api API Reference + + To browse the complete documentation of the libevent API, click on any of + the following links. + + event2/event.h + The primary libevent header + + event2/thread.h + Functions for use by multithreaded programs + + event2/buffer.h and event2/bufferevent.h + Buffer management for network reading and writing + + event2/util.h + Utility functions for portable nonblocking network code + + event2/dns.h + Asynchronous DNS resolution + + event2/http.h + An embedded libevent-based HTTP server + + event2/rpc.h + A framework for creating RPC servers and clients + + */ + +/** @file event2/event.h + + Core functions for waiting for and receiving events, and using event bases. +*/ + +#include <event2/visibility.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#include <event2/event-config.h> +#ifdef EVENT__HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef EVENT__HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + +#include <stdio.h> + +/* For int types. */ +#include <event2/util.h> + +/** + * Structure to hold information and state for a Libevent dispatch loop. + * + * The event_base lies at the center of Libevent; every application will + * have one. It keeps track of all pending and active events, and + * notifies your application of the active ones. + * + * This is an opaque structure; you can allocate one using + * event_base_new() or event_base_new_with_config(). + * + * @see event_base_new(), event_base_free(), event_base_loop(), + * event_base_new_with_config() + */ +struct event_base +#ifdef EVENT_IN_DOXYGEN_ +{/*Empty body so that doxygen will generate documentation here.*/} +#endif +; + +/** + * @struct event + * + * Structure to represent a single event. + * + * An event can have some underlying condition it represents: a socket + * becoming readable or writeable (or both), or a signal becoming raised. + * (An event that represents no underlying condition is still useful: you + * can use one to implement a timer, or to communicate between threads.) + * + * Generally, you can create events with event_new(), then make them + * pending with event_add(). As your event_base runs, it will run the + * callbacks of an events whose conditions are triggered. When you + * longer want the event, free it with event_free(). + * + * In more depth: + * + * An event may be "pending" (one whose condition we are watching), + * "active" (one whose condition has triggered and whose callback is about + * to run), neither, or both. Events come into existence via + * event_assign() or event_new(), and are then neither active nor pending. + * + * To make an event pending, pass it to event_add(). When doing so, you + * can also set a timeout for the event. + * + * Events become active during an event_base_loop() call when either their + * condition has triggered, or when their timeout has elapsed. You can + * also activate an event manually using event_active(). The even_base + * loop will run the callbacks of active events; after it has done so, it + * marks them as no longer active. + * + * You can make an event non-pending by passing it to event_del(). This + * also makes the event non-active. + * + * Events can be "persistent" or "non-persistent". A non-persistent event + * becomes non-pending as soon as it is triggered: thus, it only runs at + * most once per call to event_add(). A persistent event remains pending + * even when it becomes active: you'll need to event_del() it manually in + * order to make it non-pending. When a persistent event with a timeout + * becomes active, its timeout is reset: this means you can use persistent + * events to implement periodic timeouts. + * + * This should be treated as an opaque structure; you should never read or + * write any of its fields directly. For backward compatibility with old + * code, it is defined in the event2/event_struct.h header; including this + * header may make your code incompatible with other versions of Libevent. + * + * @see event_new(), event_free(), event_assign(), event_get_assignment(), + * event_add(), event_del(), event_active(), event_pending(), + * event_get_fd(), event_get_base(), event_get_events(), + * event_get_callback(), event_get_callback_arg(), + * event_priority_set() + */ +struct event +#ifdef EVENT_IN_DOXYGEN_ +{/*Empty body so that doxygen will generate documentation here.*/} +#endif +; + +/** + * Configuration for an event_base. + * + * There are many options that can be used to alter the behavior and + * implementation of an event_base. To avoid having to pass them all in a + * complex many-argument constructor, we provide an abstract data type + * wrhere you set up configation information before passing it to + * event_base_new_with_config(). + * + * @see event_config_new(), event_config_free(), event_base_new_with_config(), + * event_config_avoid_method(), event_config_require_features(), + * event_config_set_flag(), event_config_set_num_cpus_hint() + */ +struct event_config +#ifdef EVENT_IN_DOXYGEN_ +{/*Empty body so that doxygen will generate documentation here.*/} +#endif +; + +/** + * Enable some relatively expensive debugging checks in Libevent that + * would normally be turned off. Generally, these checks cause code that + * would otherwise crash mysteriously to fail earlier with an assertion + * failure. Note that this method MUST be called before any events or + * event_bases have been created. + * + * Debug mode can currently catch the following errors: + * An event is re-assigned while it is added + * Any function is called on a non-assigned event + * + * Note that debugging mode uses memory to track every event that has been + * initialized (via event_assign, event_set, or event_new) but not yet + * released (via event_free or event_debug_unassign). If you want to use + * debug mode, and you find yourself running out of memory, you will need + * to use event_debug_unassign to explicitly stop tracking events that + * are no longer considered set-up. + * + * @see event_debug_unassign() + */ +EVENT2_EXPORT_SYMBOL +void event_enable_debug_mode(void); + +/** + * When debugging mode is enabled, informs Libevent that an event should no + * longer be considered as assigned. When debugging mode is not enabled, does + * nothing. + * + * This function must only be called on a non-added event. + * + * @see event_enable_debug_mode() + */ +EVENT2_EXPORT_SYMBOL +void event_debug_unassign(struct event *); + +/** + * Create and return a new event_base to use with the rest of Libevent. + * + * @return a new event_base on success, or NULL on failure. + * + * @see event_base_free(), event_base_new_with_config() + */ +EVENT2_EXPORT_SYMBOL +struct event_base *event_base_new(void); + +/** + Reinitialize the event base after a fork + + Some event mechanisms do not survive across fork. The event base needs + to be reinitialized with the event_reinit() function. + + @param base the event base that needs to be re-initialized + @return 0 if successful, or -1 if some events could not be re-added. + @see event_base_new() +*/ +EVENT2_EXPORT_SYMBOL +int event_reinit(struct event_base *base); + +/** + Event dispatching loop + + This loop will run the event base until either there are no more pending or + active, or until something calls event_base_loopbreak() or + event_base_loopexit(). + + @param base the event_base structure returned by event_base_new() or + event_base_new_with_config() + @return 0 if successful, -1 if an error occurred, or 1 if we exited because + no events were pending or active. + @see event_base_loop() + */ +EVENT2_EXPORT_SYMBOL +int event_base_dispatch(struct event_base *); + +/** + Get the kernel event notification mechanism used by Libevent. + + @param eb the event_base structure returned by event_base_new() + @return a string identifying the kernel event mechanism (kqueue, epoll, etc.) + */ +EVENT2_EXPORT_SYMBOL +const char *event_base_get_method(const struct event_base *); + +/** + Gets all event notification mechanisms supported by Libevent. + + This functions returns the event mechanism in order preferred by + Libevent. Note that this list will include all backends that + Libevent has compiled-in support for, and will not necessarily check + your OS to see whether it has the required resources. + + @return an array with pointers to the names of support methods. + The end of the array is indicated by a NULL pointer. If an + error is encountered NULL is returned. +*/ +EVENT2_EXPORT_SYMBOL +const char **event_get_supported_methods(void); + +/** Query the current monotonic time from a the timer for a struct + * event_base. + */ +EVENT2_EXPORT_SYMBOL +int event_gettime_monotonic(struct event_base *base, struct timeval *tp); + +/** + @name event type flag + + Flags to pass to event_base_get_num_events() to specify the kinds of events + we want to aggregate counts for +*/ +/**@{*/ +/** count the number of active events, which have been triggered.*/ +#define EVENT_BASE_COUNT_ACTIVE 1U +/** count the number of virtual events, which is used to represent an internal + * condition, other than a pending event, that keeps the loop from exiting. */ +#define EVENT_BASE_COUNT_VIRTUAL 2U +/** count the number of events which have been added to event base, including + * internal events. */ +#define EVENT_BASE_COUNT_ADDED 4U +/**@}*/ + +/** + Gets the number of events in event_base, as specified in the flags. + + Since event base has some internal events added to make some of its + functionalities work, EVENT_BASE_COUNT_ADDED may return more than the + number of events you added using event_add(). + + If you pass EVENT_BASE_COUNT_ACTIVE and EVENT_BASE_COUNT_ADDED together, an + active event will be counted twice. However, this might not be the case in + future libevent versions. The return value is an indication of the work + load, but the user shouldn't rely on the exact value as this may change in + the future. + + @param eb the event_base structure returned by event_base_new() + @param flags a bitwise combination of the kinds of events to aggregate + counts for + @return the number of events specified in the flags +*/ +EVENT2_EXPORT_SYMBOL +int event_base_get_num_events(struct event_base *, unsigned int); + +/** + Get the maximum number of events in a given event_base as specified in the + flags. + + @param eb the event_base structure returned by event_base_new() + @param flags a bitwise combination of the kinds of events to aggregate + counts for + @param clear option used to reset the maximum count. + @return the number of events specified in the flags + */ +EVENT2_EXPORT_SYMBOL +int event_base_get_max_events(struct event_base *, unsigned int, int); + +/** + Allocates a new event configuration object. + + The event configuration object can be used to change the behavior of + an event base. + + @return an event_config object that can be used to store configuration, or + NULL if an error is encountered. + @see event_base_new_with_config(), event_config_free(), event_config +*/ +EVENT2_EXPORT_SYMBOL +struct event_config *event_config_new(void); + +/** + Deallocates all memory associated with an event configuration object + + @param cfg the event configuration object to be freed. +*/ +EVENT2_EXPORT_SYMBOL +void event_config_free(struct event_config *cfg); + +/** + Enters an event method that should be avoided into the configuration. + + This can be used to avoid event mechanisms that do not support certain + file descriptor types, or for debugging to avoid certain event + mechanisms. An application can make use of multiple event bases to + accommodate incompatible file descriptor types. + + @param cfg the event configuration object + @param method the name of the event method to avoid + @return 0 on success, -1 on failure. +*/ +EVENT2_EXPORT_SYMBOL +int event_config_avoid_method(struct event_config *cfg, const char *method); + +/** + A flag used to describe which features an event_base (must) provide. + + Because of OS limitations, not every Libevent backend supports every + possible feature. You can use this type with + event_config_require_features() to tell Libevent to only proceed if your + event_base implements a given feature, and you can receive this type from + event_base_get_features() to see which features are available. +*/ +enum event_method_feature { + /** Require an event method that allows edge-triggered events with EV_ET. */ + EV_FEATURE_ET = 0x01, + /** Require an event method where having one event triggered among + * many is [approximately] an O(1) operation. This excludes (for + * example) select and poll, which are approximately O(N) for N + * equal to the total number of possible events. */ + EV_FEATURE_O1 = 0x02, + /** Require an event method that allows file descriptors as well as + * sockets. */ + EV_FEATURE_FDS = 0x04, + /** Require an event method that allows you to use EV_CLOSED to detect + * connection close without the necessity of reading all the pending data. + * + * Methods that do support EV_CLOSED may not be able to provide support on + * all kernel versions. + **/ + EV_FEATURE_EARLY_CLOSE = 0x08 +}; + +/** + A flag passed to event_config_set_flag(). + + These flags change the behavior of an allocated event_base. + + @see event_config_set_flag(), event_base_new_with_config(), + event_method_feature + */ +enum event_base_config_flag { + /** Do not allocate a lock for the event base, even if we have + locking set up. + + Setting this option will make it unsafe and nonfunctional to call + functions on the base concurrently from multiple threads. + */ + EVENT_BASE_FLAG_NOLOCK = 0x01, + /** Do not check the EVENT_* environment variables when configuring + an event_base */ + EVENT_BASE_FLAG_IGNORE_ENV = 0x02, + /** Windows only: enable the IOCP dispatcher at startup + + If this flag is set then bufferevent_socket_new() and + evconn_listener_new() will use IOCP-backed implementations + instead of the usual select-based one on Windows. + */ + EVENT_BASE_FLAG_STARTUP_IOCP = 0x04, + /** Instead of checking the current time every time the event loop is + ready to run timeout callbacks, check after each timeout callback. + */ + EVENT_BASE_FLAG_NO_CACHE_TIME = 0x08, + + /** If we are using the epoll backend, this flag says that it is + safe to use Libevent's internal change-list code to batch up + adds and deletes in order to try to do as few syscalls as + possible. Setting this flag can make your code run faster, but + it may trigger a Linux bug: it is not safe to use this flag + if you have any fds cloned by dup() or its variants. Doing so + will produce strange and hard-to-diagnose bugs. + + This flag can also be activated by setting the + EVENT_EPOLL_USE_CHANGELIST environment variable. + + This flag has no effect if you wind up using a backend other than + epoll. + */ + EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST = 0x10, + + /** Ordinarily, Libevent implements its time and timeout code using + the fastest monotonic timer that we have. If this flag is set, + however, we use less efficient more precise timer, assuming one is + present. + */ + EVENT_BASE_FLAG_PRECISE_TIMER = 0x20 +}; + +/** + Return a bitmask of the features implemented by an event base. This + will be a bitwise OR of one or more of the values of + event_method_feature + + @see event_method_feature + */ +EVENT2_EXPORT_SYMBOL +int event_base_get_features(const struct event_base *base); + +/** + Enters a required event method feature that the application demands. + + Note that not every feature or combination of features is supported + on every platform. Code that requests features should be prepared + to handle the case where event_base_new_with_config() returns NULL, as in: + <pre> + event_config_require_features(cfg, EV_FEATURE_ET); + base = event_base_new_with_config(cfg); + if (base == NULL) { + // We can't get edge-triggered behavior here. + event_config_require_features(cfg, 0); + base = event_base_new_with_config(cfg); + } + </pre> + + @param cfg the event configuration object + @param feature a bitfield of one or more event_method_feature values. + Replaces values from previous calls to this function. + @return 0 on success, -1 on failure. + @see event_method_feature, event_base_new_with_config() +*/ +EVENT2_EXPORT_SYMBOL +int event_config_require_features(struct event_config *cfg, int feature); + +/** + * Sets one or more flags to configure what parts of the eventual event_base + * will be initialized, and how they'll work. + * + * @see event_base_config_flags, event_base_new_with_config() + **/ +EVENT2_EXPORT_SYMBOL +int event_config_set_flag(struct event_config *cfg, int flag); + +/** + * Records a hint for the number of CPUs in the system. This is used for + * tuning thread pools, etc, for optimal performance. In Libevent 2.0, + * it is only on Windows, and only when IOCP is in use. + * + * @param cfg the event configuration object + * @param cpus the number of cpus + * @return 0 on success, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int event_config_set_num_cpus_hint(struct event_config *cfg, int cpus); + +/** + * Record an interval and/or a number of callbacks after which the event base + * should check for new events. By default, the event base will run as many + * events are as activated at the higest activated priority before checking + * for new events. If you configure it by setting max_interval, it will check + * the time after each callback, and not allow more than max_interval to + * elapse before checking for new events. If you configure it by setting + * max_callbacks to a value >= 0, it will run no more than max_callbacks + * callbacks before checking for new events. + * + * This option can decrease the latency of high-priority events, and + * avoid priority inversions where multiple low-priority events keep us from + * polling for high-priority events, but at the expense of slightly decreasing + * the throughput. Use it with caution! + * + * @param cfg The event_base configuration object. + * @param max_interval An interval after which Libevent should stop running + * callbacks and check for more events, or NULL if there should be + * no such interval. + * @param max_callbacks A number of callbacks after which Libevent should + * stop running callbacks and check for more events, or -1 if there + * should be no such limit. + * @param min_priority A priority below which max_interval and max_callbacks + * should not be enforced. If this is set to 0, they are enforced + * for events of every priority; if it's set to 1, they're enforced + * for events of priority 1 and above, and so on. + * @return 0 on success, -1 on failure. + **/ +EVENT2_EXPORT_SYMBOL +int event_config_set_max_dispatch_interval(struct event_config *cfg, + const struct timeval *max_interval, int max_callbacks, + int min_priority); + +/** + Initialize the event API. + + Use event_base_new_with_config() to initialize a new event base, taking + the specified configuration under consideration. The configuration object + can currently be used to avoid certain event notification mechanisms. + + @param cfg the event configuration object + @return an initialized event_base that can be used to registering events, + or NULL if no event base can be created with the requested event_config. + @see event_base_new(), event_base_free(), event_init(), event_assign() +*/ +EVENT2_EXPORT_SYMBOL +struct event_base *event_base_new_with_config(const struct event_config *); + +/** + Deallocate all memory associated with an event_base, and free the base. + + Note that this function will not close any fds or free any memory passed + to event_new as the argument to callback. + + If there are any pending finalizer callbacks, this function will invoke + them. + + @param eb an event_base to be freed + */ +EVENT2_EXPORT_SYMBOL +void event_base_free(struct event_base *); + +/** + As event_free, but do not run finalizers. + + THIS IS AN EXPERIMENTAL API. IT MIGHT CHANGE BEFORE THE LIBEVENT 2.1 SERIES + BECOMES STABLE. + */ +EVENT2_EXPORT_SYMBOL +void event_base_free_nofinalize(struct event_base *); + +/** @name Log severities + */ +/**@{*/ +#define EVENT_LOG_DEBUG 0 +#define EVENT_LOG_MSG 1 +#define EVENT_LOG_WARN 2 +#define EVENT_LOG_ERR 3 +/**@}*/ + +/* Obsolete names: these are deprecated, but older programs might use them. + * They violate the reserved-identifier namespace. */ +#define _EVENT_LOG_DEBUG EVENT_LOG_DEBUG +#define _EVENT_LOG_MSG EVENT_LOG_MSG +#define _EVENT_LOG_WARN EVENT_LOG_WARN +#define _EVENT_LOG_ERR EVENT_LOG_ERR + +/** + A callback function used to intercept Libevent's log messages. + + @see event_set_log_callback + */ +typedef void (*event_log_cb)(int severity, const char *msg); +/** + Redirect Libevent's log messages. + + @param cb a function taking two arguments: an integer severity between + EVENT_LOG_DEBUG and EVENT_LOG_ERR, and a string. If cb is NULL, + then the default log is used. + + NOTE: The function you provide *must not* call any other libevent + functionality. Doing so can produce undefined behavior. + */ +EVENT2_EXPORT_SYMBOL +void event_set_log_callback(event_log_cb cb); + +/** + A function to be called if Libevent encounters a fatal internal error. + + @see event_set_fatal_callback + */ +typedef void (*event_fatal_cb)(int err); + +/** + Override Libevent's behavior in the event of a fatal internal error. + + By default, Libevent will call exit(1) if a programming error makes it + impossible to continue correct operation. This function allows you to supply + another callback instead. Note that if the function is ever invoked, + something is wrong with your program, or with Libevent: any subsequent calls + to Libevent may result in undefined behavior. + + Libevent will (almost) always log an EVENT_LOG_ERR message before calling + this function; look at the last log message to see why Libevent has died. + */ +EVENT2_EXPORT_SYMBOL +void event_set_fatal_callback(event_fatal_cb cb); + +#define EVENT_DBG_ALL 0xffffffffu +#define EVENT_DBG_NONE 0 + +/** + Turn on debugging logs and have them sent to the default log handler. + + This is a global setting; if you are going to call it, you must call this + before any calls that create an event-base. You must call it before any + multithreaded use of Libevent. + + Debug logs are verbose. + + @param which Controls which debug messages are turned on. This option is + unused for now; for forward compatibility, you must pass in the constant + "EVENT_DBG_ALL" to turn debugging logs on, or "EVENT_DBG_NONE" to turn + debugging logs off. + */ +EVENT2_EXPORT_SYMBOL +void event_enable_debug_logging(ev_uint32_t which); + +/** + Associate a different event base with an event. + + The event to be associated must not be currently active or pending. + + @param eb the event base + @param ev the event + @return 0 on success, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int event_base_set(struct event_base *, struct event *); + +/** @name Loop flags + + These flags control the behavior of event_base_loop(). + */ +/**@{*/ +/** Block until we have an active event, then exit once all active events + * have had their callbacks run. */ +#define EVLOOP_ONCE 0x01 +/** Do not block: see which events are ready now, run the callbacks + * of the highest-priority ones, then exit. */ +#define EVLOOP_NONBLOCK 0x02 +/** Do not exit the loop because we have no pending events. Instead, keep + * running until event_base_loopexit() or event_base_loopbreak() makes us + * stop. + */ +#define EVLOOP_NO_EXIT_ON_EMPTY 0x04 +/**@}*/ + +/** + Wait for events to become active, and run their callbacks. + + This is a more flexible version of event_base_dispatch(). + + By default, this loop will run the event base until either there are no more + pending or active events, or until something calls event_base_loopbreak() or + event_base_loopexit(). You can override this behavior with the 'flags' + argument. + + @param eb the event_base structure returned by event_base_new() or + event_base_new_with_config() + @param flags any combination of EVLOOP_ONCE | EVLOOP_NONBLOCK + @return 0 if successful, -1 if an error occurred, or 1 if we exited because + no events were pending or active. + @see event_base_loopexit(), event_base_dispatch(), EVLOOP_ONCE, + EVLOOP_NONBLOCK + */ +EVENT2_EXPORT_SYMBOL +int event_base_loop(struct event_base *, int); + +/** + Exit the event loop after the specified time + + The next event_base_loop() iteration after the given timer expires will + complete normally (handling all queued events) then exit without + blocking for events again. + + Subsequent invocations of event_base_loop() will proceed normally. + + @param eb the event_base structure returned by event_init() + @param tv the amount of time after which the loop should terminate, + or NULL to exit after running all currently active events. + @return 0 if successful, or -1 if an error occurred + @see event_base_loopbreak() + */ +EVENT2_EXPORT_SYMBOL +int event_base_loopexit(struct event_base *, const struct timeval *); + +/** + Abort the active event_base_loop() immediately. + + event_base_loop() will abort the loop after the next event is completed; + event_base_loopbreak() is typically invoked from this event's callback. + This behavior is analogous to the "break;" statement. + + Subsequent invocations of event_base_loop() will proceed normally. + + @param eb the event_base structure returned by event_init() + @return 0 if successful, or -1 if an error occurred + @see event_base_loopexit() + */ +EVENT2_EXPORT_SYMBOL +int event_base_loopbreak(struct event_base *); + +/** + Tell the active event_base_loop() to scan for new events immediately. + + Calling this function makes the currently active event_base_loop() + start the loop over again (scanning for new events) after the current + event callback finishes. If the event loop is not running, this + function has no effect. + + event_base_loopbreak() is typically invoked from this event's callback. + This behavior is analogous to the "continue;" statement. + + Subsequent invocations of event loop will proceed normally. + + @param eb the event_base structure returned by event_init() + @return 0 if successful, or -1 if an error occurred + @see event_base_loopbreak() + */ +EVENT2_EXPORT_SYMBOL +int event_base_loopcontinue(struct event_base *); + +/** + Checks if the event loop was told to exit by event_base_loopexit(). + + This function will return true for an event_base at every point after + event_loopexit() is called, until the event loop is next entered. + + @param eb the event_base structure returned by event_init() + @return true if event_base_loopexit() was called on this event base, + or 0 otherwise + @see event_base_loopexit() + @see event_base_got_break() + */ +EVENT2_EXPORT_SYMBOL +int event_base_got_exit(struct event_base *); + +/** + Checks if the event loop was told to abort immediately by event_base_loopbreak(). + + This function will return true for an event_base at every point after + event_base_loopbreak() is called, until the event loop is next entered. + + @param eb the event_base structure returned by event_init() + @return true if event_base_loopbreak() was called on this event base, + or 0 otherwise + @see event_base_loopbreak() + @see event_base_got_exit() + */ +EVENT2_EXPORT_SYMBOL +int event_base_got_break(struct event_base *); + +/** + * @name event flags + * + * Flags to pass to event_new(), event_assign(), event_pending(), and + * anything else with an argument of the form "short events" + */ +/**@{*/ +/** Indicates that a timeout has occurred. It's not necessary to pass + * this flag to event_for new()/event_assign() to get a timeout. */ +#define EV_TIMEOUT 0x01 +/** Wait for a socket or FD to become readable */ +#define EV_READ 0x02 +/** Wait for a socket or FD to become writeable */ +#define EV_WRITE 0x04 +/** Wait for a POSIX signal to be raised*/ +#define EV_SIGNAL 0x08 +/** + * Persistent event: won't get removed automatically when activated. + * + * When a persistent event with a timeout becomes activated, its timeout + * is reset to 0. + */ +#define EV_PERSIST 0x10 +/** Select edge-triggered behavior, if supported by the backend. */ +#define EV_ET 0x20 +/** + * If this option is provided, then event_del() will not block in one thread + * while waiting for the event callback to complete in another thread. + * + * To use this option safely, you may need to use event_finalize() or + * event_free_finalize() in order to safely tear down an event in a + * multithreaded application. See those functions for more information. + * + * THIS IS AN EXPERIMENTAL API. IT MIGHT CHANGE BEFORE THE LIBEVENT 2.1 SERIES + * BECOMES STABLE. + **/ +#define EV_FINALIZE 0x40 +/** + * Detects connection close events. You can use this to detect when a + * connection has been closed, without having to read all the pending data + * from a connection. + * + * Not all backends support EV_CLOSED. To detect or require it, use the + * feature flag EV_FEATURE_EARLY_CLOSE. + **/ +#define EV_CLOSED 0x80 +/**@}*/ + +/** + @name evtimer_* macros + + Aliases for working with one-shot timer events */ +/**@{*/ +#define evtimer_assign(ev, b, cb, arg) \ + event_assign((ev), (b), -1, 0, (cb), (arg)) +#define evtimer_new(b, cb, arg) event_new((b), -1, 0, (cb), (arg)) +#define evtimer_add(ev, tv) event_add((ev), (tv)) +#define evtimer_del(ev) event_del(ev) +#define evtimer_pending(ev, tv) event_pending((ev), EV_TIMEOUT, (tv)) +#define evtimer_initialized(ev) event_initialized(ev) +/**@}*/ + +/** + @name evsignal_* macros + + Aliases for working with signal events + */ +/**@{*/ +#define evsignal_add(ev, tv) event_add((ev), (tv)) +#define evsignal_assign(ev, b, x, cb, arg) \ + event_assign((ev), (b), (x), EV_SIGNAL|EV_PERSIST, cb, (arg)) +#define evsignal_new(b, x, cb, arg) \ + event_new((b), (x), EV_SIGNAL|EV_PERSIST, (cb), (arg)) +#define evsignal_del(ev) event_del(ev) +#define evsignal_pending(ev, tv) event_pending((ev), EV_SIGNAL, (tv)) +#define evsignal_initialized(ev) event_initialized(ev) +/**@}*/ + +/** + A callback function for an event. + + It receives three arguments: + + @param fd An fd or signal + @param events One or more EV_* flags + @param arg A user-supplied argument. + + @see event_new() + */ +typedef void (*event_callback_fn)(evutil_socket_t, short, void *); + +/** + Return a value used to specify that the event itself must be used as the callback argument. + + The function event_new() takes a callback argument which is passed + to the event's callback function. To specify that the argument to be + passed to the callback function is the event that event_new() returns, + pass in the return value of event_self_cbarg() as the callback argument + for event_new(). + + For example: + <pre> + struct event *ev = event_new(base, sock, events, callback, %event_self_cbarg()); + </pre> + + For consistency with event_new(), it is possible to pass the return value + of this function as the callback argument for event_assign() – this + achieves the same result as passing the event in directly. + + @return a value to be passed as the callback argument to event_new() or + event_assign(). + @see event_new(), event_assign() + */ +EVENT2_EXPORT_SYMBOL +void *event_self_cbarg(void); + +/** + Allocate and asssign a new event structure, ready to be added. + + The function event_new() returns a new event that can be used in + future calls to event_add() and event_del(). The fd and events + arguments determine which conditions will trigger the event; the + callback and callback_arg arguments tell Libevent what to do when the + event becomes active. + + If events contains one of EV_READ, EV_WRITE, or EV_READ|EV_WRITE, then + fd is a file descriptor or socket that should get monitored for + readiness to read, readiness to write, or readiness for either operation + (respectively). If events contains EV_SIGNAL, then fd is a signal + number to wait for. If events contains none of those flags, then the + event can be triggered only by a timeout or by manual activation with + event_active(): In this case, fd must be -1. + + The EV_PERSIST flag can also be passed in the events argument: it makes + event_add() persistent until event_del() is called. + + The EV_ET flag is compatible with EV_READ and EV_WRITE, and supported + only by certain backends. It tells Libevent to use edge-triggered + events. + + The EV_TIMEOUT flag has no effect here. + + It is okay to have multiple events all listening on the same fds; but + they must either all be edge-triggered, or all not be edge triggerd. + + When the event becomes active, the event loop will run the provided + callbuck function, with three arguments. The first will be the provided + fd value. The second will be a bitfield of the events that triggered: + EV_READ, EV_WRITE, or EV_SIGNAL. Here the EV_TIMEOUT flag indicates + that a timeout occurred, and EV_ET indicates that an edge-triggered + event occurred. The third event will be the callback_arg pointer that + you provide. + + @param base the event base to which the event should be attached. + @param fd the file descriptor or signal to be monitored, or -1. + @param events desired events to monitor: bitfield of EV_READ, EV_WRITE, + EV_SIGNAL, EV_PERSIST, EV_ET. + @param callback callback function to be invoked when the event occurs + @param callback_arg an argument to be passed to the callback function + + @return a newly allocated struct event that must later be freed with + event_free(). + @see event_free(), event_add(), event_del(), event_assign() + */ +EVENT2_EXPORT_SYMBOL +struct event *event_new(struct event_base *, evutil_socket_t, short, event_callback_fn, void *); + + +/** + Prepare a new, already-allocated event structure to be added. + + The function event_assign() prepares the event structure ev to be used + in future calls to event_add() and event_del(). Unlike event_new(), it + doesn't allocate memory itself: it requires that you have already + allocated a struct event, probably on the heap. Doing this will + typically make your code depend on the size of the event structure, and + thereby create incompatibility with future versions of Libevent. + + The easiest way to avoid this problem is just to use event_new() and + event_free() instead. + + A slightly harder way to future-proof your code is to use + event_get_struct_event_size() to determine the required size of an event + at runtime. + + Note that it is NOT safe to call this function on an event that is + active or pending. Doing so WILL corrupt internal data structures in + Libevent, and lead to strange, hard-to-diagnose bugs. You _can_ use + event_assign to change an existing event, but only if it is not active + or pending! + + The arguments for this function, and the behavior of the events that it + makes, are as for event_new(). + + @param ev an event struct to be modified + @param base the event base to which ev should be attached. + @param fd the file descriptor to be monitored + @param events desired events to monitor; can be EV_READ and/or EV_WRITE + @param callback callback function to be invoked when the event occurs + @param callback_arg an argument to be passed to the callback function + + @return 0 if success, or -1 on invalid arguments. + + @see event_new(), event_add(), event_del(), event_base_once(), + event_get_struct_event_size() + */ +EVENT2_EXPORT_SYMBOL +int event_assign(struct event *, struct event_base *, evutil_socket_t, short, event_callback_fn, void *); + +/** + Deallocate a struct event * returned by event_new(). + + If the event is pending or active, first make it non-pending and + non-active. + */ +EVENT2_EXPORT_SYMBOL +void event_free(struct event *); + +/** + * Callback type for event_finalize and event_free_finalize(). + * + * THIS IS AN EXPERIMENTAL API. IT MIGHT CHANGE BEFORE THE LIBEVENT 2.1 SERIES + * BECOMES STABLE. + * + **/ +typedef void (*event_finalize_callback_fn)(struct event *, void *); +/** + @name Finalization functions + + These functions are used to safely tear down an event in a multithreaded + application. If you construct your events with EV_FINALIZE to avoid + deadlocks, you will need a way to remove an event in the certainty that + it will definitely not be running its callback when you deallocate it + and its callback argument. + + To do this, call one of event_finalize() or event_free_finalize with + 0 for its first argument, the event to tear down as its second argument, + and a callback function as its third argument. The callback will be + invoked as part of the event loop, with the event's priority. + + After you call a finalizer function, event_add() and event_active() will + no longer work on the event, and event_del() will produce a no-op. You + must not try to change the event's fields with event_assign() or + event_set() while the finalize callback is in progress. Once the + callback has been invoked, you should treat the event structure as + containing uninitialized memory. + + The event_free_finalize() function frees the event after it's finalized; + event_finalize() does not. + + A finalizer callback must not make events pending or active. It must not + add events, activate events, or attempt to "resucitate" the event being + finalized in any way. + + THIS IS AN EXPERIMENTAL API. IT MIGHT CHANGE BEFORE THE LIBEVENT 2.1 SERIES + BECOMES STABLE. + + @return 0 on succes, -1 on failure. + */ +/**@{*/ +EVENT2_EXPORT_SYMBOL +int event_finalize(unsigned, struct event *, event_finalize_callback_fn); +EVENT2_EXPORT_SYMBOL +int event_free_finalize(unsigned, struct event *, event_finalize_callback_fn); +/**@}*/ + +/** + Schedule a one-time event + + The function event_base_once() is similar to event_new(). However, it + schedules a callback to be called exactly once, and does not require the + caller to prepare an event structure. + + Note that in Libevent 2.0 and earlier, if the event is never triggered, the + internal memory used to hold it will never be freed. In Libevent 2.1, + the internal memory will get freed by event_base_free() if the event + is never triggered. The 'arg' value, however, will not get freed in either + case--you'll need to free that on your own if you want it to go away. + + @param base an event_base + @param fd a file descriptor to monitor, or -1 for no fd. + @param events event(s) to monitor; can be any of EV_READ | + EV_WRITE, or EV_TIMEOUT + @param callback callback function to be invoked when the event occurs + @param arg an argument to be passed to the callback function + @param timeout the maximum amount of time to wait for the event. NULL + makes an EV_READ/EV_WRITE event make forever; NULL makes an + EV_TIMEOUT event succees immediately. + @return 0 if successful, or -1 if an error occurred + */ +EVENT2_EXPORT_SYMBOL +int event_base_once(struct event_base *, evutil_socket_t, short, event_callback_fn, void *, const struct timeval *); + +/** + Add an event to the set of pending events. + + The function event_add() schedules the execution of the event 'ev' when the + condition specified by event_assign() or event_new() occurs, or when the time + specified in timeout has elapesed. If atimeout is NULL, no timeout + occurs and the function will only be + called if a matching event occurs. The event in the + ev argument must be already initialized by event_assign() or event_new() + and may not be used + in calls to event_assign() until it is no longer pending. + + If the event in the ev argument already has a scheduled timeout, calling + event_add() replaces the old timeout with the new one if tv is non-NULL. + + @param ev an event struct initialized via event_assign() or event_new() + @param timeout the maximum amount of time to wait for the event, or NULL + to wait forever + @return 0 if successful, or -1 if an error occurred + @see event_del(), event_assign(), event_new() + */ +EVENT2_EXPORT_SYMBOL +int event_add(struct event *ev, const struct timeval *timeout); + +/** + Remove a timer from a pending event without removing the event itself. + + If the event has a scheduled timeout, this function unschedules it but + leaves the event otherwise pending. + + @param ev an event struct initialized via event_assign() or event_new() + @return 0 on success, or -1 if an error occurrect. +*/ +EVENT2_EXPORT_SYMBOL +int event_remove_timer(struct event *ev); + +/** + Remove an event from the set of monitored events. + + The function event_del() will cancel the event in the argument ev. If the + event has already executed or has never been added the call will have no + effect. + + @param ev an event struct to be removed from the working set + @return 0 if successful, or -1 if an error occurred + @see event_add() + */ +EVENT2_EXPORT_SYMBOL +int event_del(struct event *); + +/** + As event_del(), but never blocks while the event's callback is running + in another thread, even if the event was constructed without the + EV_FINALIZE flag. + + THIS IS AN EXPERIMENTAL API. IT MIGHT CHANGE BEFORE THE LIBEVENT 2.1 SERIES + BECOMES STABLE. + */ +EVENT2_EXPORT_SYMBOL +int event_del_noblock(struct event *ev); +/** + As event_del(), but always blocks while the event's callback is running + in another thread, even if the event was constructed with the + EV_FINALIZE flag. + + THIS IS AN EXPERIMENTAL API. IT MIGHT CHANGE BEFORE THE LIBEVENT 2.1 SERIES + BECOMES STABLE. + */ +EVENT2_EXPORT_SYMBOL +int event_del_block(struct event *ev); + +/** + Make an event active. + + You can use this function on a pending or a non-pending event to make it + active, so that its callback will be run by event_base_dispatch() or + event_base_loop(). + + One common use in multithreaded programs is to wake the thread running + event_base_loop() from another thread. + + @param ev an event to make active. + @param res a set of flags to pass to the event's callback. + @param ncalls an obsolete argument: this is ignored. + **/ +EVENT2_EXPORT_SYMBOL +void event_active(struct event *ev, int res, short ncalls); + +/** + Checks if a specific event is pending or scheduled. + + @param ev an event struct previously passed to event_add() + @param events the requested event type; any of EV_TIMEOUT|EV_READ| + EV_WRITE|EV_SIGNAL + @param tv if this field is not NULL, and the event has a timeout, + this field is set to hold the time at which the timeout will + expire. + + @return true if the event is pending on any of the events in 'what', (that + is to say, it has been added), or 0 if the event is not added. + */ +EVENT2_EXPORT_SYMBOL +int event_pending(const struct event *ev, short events, struct timeval *tv); + +/** + If called from within the callback for an event, returns that event. + + The behavior of this function is not defined when called from outside the + callback function for an event. + */ +EVENT2_EXPORT_SYMBOL +struct event *event_base_get_running_event(struct event_base *base); + +/** + Test if an event structure might be initialized. + + The event_initialized() function can be used to check if an event has been + initialized. + + Warning: This function is only useful for distinguishing a a zeroed-out + piece of memory from an initialized event, it can easily be confused by + uninitialized memory. Thus, it should ONLY be used to distinguish an + initialized event from zero. + + @param ev an event structure to be tested + @return 1 if the structure might be initialized, or 0 if it has not been + initialized + */ +EVENT2_EXPORT_SYMBOL +int event_initialized(const struct event *ev); + +/** + Get the signal number assigned to a signal event +*/ +#define event_get_signal(ev) ((int)event_get_fd(ev)) + +/** + Get the socket or signal assigned to an event, or -1 if the event has + no socket. +*/ +EVENT2_EXPORT_SYMBOL +evutil_socket_t event_get_fd(const struct event *ev); + +/** + Get the event_base associated with an event. +*/ +EVENT2_EXPORT_SYMBOL +struct event_base *event_get_base(const struct event *ev); + +/** + Return the events (EV_READ, EV_WRITE, etc) assigned to an event. +*/ +EVENT2_EXPORT_SYMBOL +short event_get_events(const struct event *ev); + +/** + Return the callback assigned to an event. +*/ +EVENT2_EXPORT_SYMBOL +event_callback_fn event_get_callback(const struct event *ev); + +/** + Return the callback argument assigned to an event. +*/ +EVENT2_EXPORT_SYMBOL +void *event_get_callback_arg(const struct event *ev); + +/** + Return the priority of an event. + @see event_priority_init(), event_get_priority() +*/ +EVENT2_EXPORT_SYMBOL +int event_get_priority(const struct event *ev); + +/** + Extract _all_ of arguments given to construct a given event. The + event_base is copied into *base_out, the fd is copied into *fd_out, and so + on. + + If any of the "_out" arguments is NULL, it will be ignored. + */ +EVENT2_EXPORT_SYMBOL +void event_get_assignment(const struct event *event, + struct event_base **base_out, evutil_socket_t *fd_out, short *events_out, + event_callback_fn *callback_out, void **arg_out); + +/** + Return the size of struct event that the Libevent library was compiled + with. + + This will be NO GREATER than sizeof(struct event) if you're running with + the same version of Libevent that your application was built with, but + otherwise might not. + + Note that it might be SMALLER than sizeof(struct event) if some future + version of Libevent adds extra padding to the end of struct event. + We might do this to help ensure ABI-compatibility between different + versions of Libevent. + */ +EVENT2_EXPORT_SYMBOL +size_t event_get_struct_event_size(void); + +/** + Get the Libevent version. + + Note that this will give you the version of the library that you're + currently linked against, not the version of the headers that you've + compiled against. + + @return a string containing the version number of Libevent +*/ +EVENT2_EXPORT_SYMBOL +const char *event_get_version(void); + +/** + Return a numeric representation of Libevent's version. + + Note that this will give you the version of the library that you're + currently linked against, not the version of the headers you've used to + compile. + + The format uses one byte each for the major, minor, and patchlevel parts of + the version number. The low-order byte is unused. For example, version + 2.0.1-alpha has a numeric representation of 0x02000100 +*/ +EVENT2_EXPORT_SYMBOL +ev_uint32_t event_get_version_number(void); + +/** As event_get_version, but gives the version of Libevent's headers. */ +#define LIBEVENT_VERSION EVENT__VERSION +/** As event_get_version_number, but gives the version number of Libevent's + * headers. */ +#define LIBEVENT_VERSION_NUMBER EVENT__NUMERIC_VERSION + +/** Largest number of priorities that Libevent can support. */ +#define EVENT_MAX_PRIORITIES 256 +/** + Set the number of different event priorities + + By default Libevent schedules all active events with the same priority. + However, some time it is desirable to process some events with a higher + priority than others. For that reason, Libevent supports strict priority + queues. Active events with a lower priority are always processed before + events with a higher priority. + + The number of different priorities can be set initially with the + event_base_priority_init() function. This function should be called + before the first call to event_base_dispatch(). The + event_priority_set() function can be used to assign a priority to an + event. By default, Libevent assigns the middle priority to all events + unless their priority is explicitly set. + + Note that urgent-priority events can starve less-urgent events: after + running all urgent-priority callbacks, Libevent checks for more urgent + events again, before running less-urgent events. Less-urgent events + will not have their callbacks run until there are no events more urgent + than them that want to be active. + + @param eb the event_base structure returned by event_base_new() + @param npriorities the maximum number of priorities + @return 0 if successful, or -1 if an error occurred + @see event_priority_set() + */ +EVENT2_EXPORT_SYMBOL +int event_base_priority_init(struct event_base *, int); + +/** + Get the number of different event priorities. + + @param eb the event_base structure returned by event_base_new() + @return Number of different event priorities + @see event_base_priority_init() +*/ +EVENT2_EXPORT_SYMBOL +int event_base_get_npriorities(struct event_base *eb); + +/** + Assign a priority to an event. + + @param ev an event struct + @param priority the new priority to be assigned + @return 0 if successful, or -1 if an error occurred + @see event_priority_init(), event_get_priority() + */ +EVENT2_EXPORT_SYMBOL +int event_priority_set(struct event *, int); + +/** + Prepare an event_base to use a large number of timeouts with the same + duration. + + Libevent's default scheduling algorithm is optimized for having a large + number of timeouts with their durations more or less randomly + distributed. But if you have a large number of timeouts that all have + the same duration (for example, if you have a large number of + connections that all have a 10-second timeout), then you can improve + Libevent's performance by telling Libevent about it. + + To do this, call this function with the common duration. It will return a + pointer to a different, opaque timeout value. (Don't depend on its actual + contents!) When you use this timeout value in event_add(), Libevent will + schedule the event more efficiently. + + (This optimization probably will not be worthwhile until you have thousands + or tens of thousands of events with the same timeout.) + */ +EVENT2_EXPORT_SYMBOL +const struct timeval *event_base_init_common_timeout(struct event_base *base, + const struct timeval *duration); + +#if !defined(EVENT__DISABLE_MM_REPLACEMENT) || defined(EVENT_IN_DOXYGEN_) +/** + Override the functions that Libevent uses for memory management. + + Usually, Libevent uses the standard libc functions malloc, realloc, and + free to allocate memory. Passing replacements for those functions to + event_set_mem_functions() overrides this behavior. + + Note that all memory returned from Libevent will be allocated by the + replacement functions rather than by malloc() and realloc(). Thus, if you + have replaced those functions, it will not be appropriate to free() memory + that you get from Libevent. Instead, you must use the free_fn replacement + that you provided. + + Note also that if you are going to call this function, you should do so + before any call to any Libevent function that does allocation. + Otherwise, those funtions will allocate their memory using malloc(), but + then later free it using your provided free_fn. + + @param malloc_fn A replacement for malloc. + @param realloc_fn A replacement for realloc + @param free_fn A replacement for free. + **/ +EVENT2_EXPORT_SYMBOL +void event_set_mem_functions( + void *(*malloc_fn)(size_t sz), + void *(*realloc_fn)(void *ptr, size_t sz), + void (*free_fn)(void *ptr)); +/** This definition is present if Libevent was built with support for + event_set_mem_functions() */ +#define EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED +#endif + +/** + Writes a human-readable description of all inserted and/or active + events to a provided stdio stream. + + This is intended for debugging; its format is not guaranteed to be the same + between libevent versions. + + @param base An event_base on which to scan the events. + @param output A stdio file to write on. + */ +EVENT2_EXPORT_SYMBOL +void event_base_dump_events(struct event_base *, FILE *); + + +/** + Activates all pending events for the given fd and event mask. + + This function activates pending events only. Events which have not been + added will not become active. + + @param base the event_base on which to activate the events. + @param fd An fd to active events on. + @param events One or more of EV_{READ,WRITE}. + */ +EVENT2_EXPORT_SYMBOL +void event_base_active_by_fd(struct event_base *base, evutil_socket_t fd, short events); + +/** + Activates all pending signals with a given signal number + + This function activates pending events only. Events which have not been + added will not become active. + + @param base the event_base on which to activate the events. + @param fd The signal to active events on. + */ +EVENT2_EXPORT_SYMBOL +void event_base_active_by_signal(struct event_base *base, int sig); + +/** + * Callback for iterating events in an event base via event_base_foreach_event + */ +typedef int (*event_base_foreach_event_cb)(const struct event_base *, const struct event *, void *); + +/** + Iterate over all added or active events events in an event loop, and invoke + a given callback on each one. + + The callback must not call any function that modifies the event base, that + modifies any event in the event base, or that adds or removes any event to + the event base. Doing so is unsupported and will lead to undefined + behavior -- likely, to crashes. + + event_base_foreach_event() holds a lock on the event_base() for the whole + time it's running: slow callbacks are not advisable. + + Note that Libevent adds some events of its own to make pieces of its + functionality work. You must not assume that the only events you'll + encounter will be the ones you added yourself. + + The callback function must return 0 to continue iteration, or some other + integer to stop iterating. + + @param base An event_base on which to scan the events. + @param fn A callback function to receive the events. + @param arg An argument passed to the callback function. + @return 0 if we iterated over every event, or the value returned by the + callback function if the loop exited early. +*/ +EVENT2_EXPORT_SYMBOL +int event_base_foreach_event(struct event_base *base, event_base_foreach_event_cb fn, void *arg); + + +/** Sets 'tv' to the current time (as returned by gettimeofday()), + looking at the cached value in 'base' if possible, and calling + gettimeofday() or clock_gettime() as appropriate if there is no + cached time. + + Generally, this value will only be cached while actually + processing event callbacks, and may be very inaccuate if your + callbacks take a long time to execute. + + Returns 0 on success, negative on failure. + */ +EVENT2_EXPORT_SYMBOL +int event_base_gettimeofday_cached(struct event_base *base, + struct timeval *tv); + +/** Update cached_tv in the 'base' to the current time + * + * You can use this function is useful for selectively increasing + * the accuracy of the cached time value in 'base' during callbacks + * that take a long time to execute. + * + * This function has no effect if the base is currently not in its + * event loop, or if timeval caching is disabled via + * EVENT_BASE_FLAG_NO_CACHE_TIME. + * + * @return 0 on success, -1 on failure + */ +EVENT2_EXPORT_SYMBOL +int event_base_update_cache_time(struct event_base *base); + +/** Release up all globally-allocated resources allocated by Libevent. + + This function does not free developer-controlled resources like + event_bases, events, bufferevents, listeners, and so on. It only releases + resources like global locks that there is no other way to free. + + It is not actually necessary to call this function before exit: every + resource that it frees would be released anyway on exit. It mainly exists + so that resource-leak debugging tools don't see Libevent as holding + resources at exit. + + You should only call this function when no other Libevent functions will + be invoked -- e.g., when cleanly exiting a program. + */ +EVENT2_EXPORT_SYMBOL +void libevent_global_shutdown(void); + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_EVENT_H_INCLUDED_ */ diff --git a/src/include/event2/event_compat.h b/src/include/event2/event_compat.h new file mode 100644 index 0000000..5110175 --- /dev/null +++ b/src/include/event2/event_compat.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2000-2007 Niels Provos <[email protected]> + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EVENT2_EVENT_COMPAT_H_INCLUDED_ +#define EVENT2_EVENT_COMPAT_H_INCLUDED_ + +/** @file event2/event_compat.h + + Potentially non-threadsafe versions of the functions in event.h: provided + only for backwards compatibility. + + In the oldest versions of Libevent, event_base was not a first-class + structure. Instead, there was a single event base that every function + manipulated. Later, when separate event bases were added, the old functions + that didn't take an event_base argument needed to work by manipulating the + "current" event base. This could lead to thread-safety issues, and obscure, + hard-to-diagnose bugs. + + @deprecated All functions in this file are by definition deprecated. + */ +#include <event2/visibility.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#include <event2/event-config.h> +#ifdef EVENT__HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef EVENT__HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + +/* For int types. */ +#include <event2/util.h> + +/** + Initialize the event API. + + The event API needs to be initialized with event_init() before it can be + used. Sets the global current base that gets used for events that have no + base associated with them. + + @deprecated This function is deprecated because it replaces the "current" + event_base, and is totally unsafe for multithreaded use. The replacement + is event_base_new(). + + @see event_base_set(), event_base_new() + */ +EVENT2_EXPORT_SYMBOL +struct event_base *event_init(void); + +/** + Loop to process events. + + Like event_base_dispatch(), but uses the "current" base. + + @deprecated This function is deprecated because it is easily confused by + multiple calls to event_init(), and because it is not safe for + multithreaded use. The replacement is event_base_dispatch(). + + @see event_base_dispatch(), event_init() + */ +EVENT2_EXPORT_SYMBOL +int event_dispatch(void); + +/** + Handle events. + + This function behaves like event_base_loop(), but uses the "current" base + + @deprecated This function is deprecated because it uses the event base from + the last call to event_init, and is therefore not safe for multithreaded + use. The replacement is event_base_loop(). + + @see event_base_loop(), event_init() +*/ +EVENT2_EXPORT_SYMBOL +int event_loop(int); + + +/** + Exit the event loop after the specified time. + + This function behaves like event_base_loopexit(), except that it uses the + "current" base. + + @deprecated This function is deprecated because it uses the event base from + the last call to event_init, and is therefore not safe for multithreaded + use. The replacement is event_base_loopexit(). + + @see event_init, event_base_loopexit() + */ +EVENT2_EXPORT_SYMBOL +int event_loopexit(const struct timeval *); + + +/** + Abort the active event_loop() immediately. + + This function behaves like event_base_loopbreakt(), except that it uses the + "current" base. + + @deprecated This function is deprecated because it uses the event base from + the last call to event_init, and is therefore not safe for multithreaded + use. The replacement is event_base_loopbreak(). + + @see event_base_loopbreak(), event_init() + */ +EVENT2_EXPORT_SYMBOL +int event_loopbreak(void); + +/** + Schedule a one-time event to occur. + + @deprecated This function is obsolete, and has been replaced by + event_base_once(). Its use is deprecated because it relies on the + "current" base configured by event_init(). + + @see event_base_once() + */ +EVENT2_EXPORT_SYMBOL +int event_once(evutil_socket_t , short, + void (*)(evutil_socket_t, short, void *), void *, const struct timeval *); + + +/** + Get the kernel event notification mechanism used by Libevent. + + @deprecated This function is obsolete, and has been replaced by + event_base_get_method(). Its use is deprecated because it relies on the + "current" base configured by event_init(). + + @see event_base_get_method() + */ +EVENT2_EXPORT_SYMBOL +const char *event_get_method(void); + + +/** + Set the number of different event priorities. + + @deprecated This function is deprecated because it is easily confused by + multiple calls to event_init(), and because it is not safe for + multithreaded use. The replacement is event_base_priority_init(). + + @see event_base_priority_init() + */ +EVENT2_EXPORT_SYMBOL +int event_priority_init(int); + +/** + Prepare an event structure to be added. + + @deprecated event_set() is not recommended for new code, because it requires + a subsequent call to event_base_set() to be safe under most circumstances. + Use event_assign() or event_new() instead. + */ +EVENT2_EXPORT_SYMBOL +void event_set(struct event *, evutil_socket_t, short, void (*)(evutil_socket_t, short, void *), void *); + +#define evtimer_set(ev, cb, arg) event_set((ev), -1, 0, (cb), (arg)) +#define evsignal_set(ev, x, cb, arg) \ + event_set((ev), (x), EV_SIGNAL|EV_PERSIST, (cb), (arg)) + + +/** + @name timeout_* macros + + @deprecated These macros are deprecated because their naming is inconsistent + with the rest of Libevent. Use the evtimer_* macros instead. + @{ + */ +#define timeout_add(ev, tv) event_add((ev), (tv)) +#define timeout_set(ev, cb, arg) event_set((ev), -1, 0, (cb), (arg)) +#define timeout_del(ev) event_del(ev) +#define timeout_pending(ev, tv) event_pending((ev), EV_TIMEOUT, (tv)) +#define timeout_initialized(ev) event_initialized(ev) +/**@}*/ + +/** + @name signal_* macros + + @deprecated These macros are deprecated because their naming is inconsistent + with the rest of Libevent. Use the evsignal_* macros instead. + @{ + */ +#define signal_add(ev, tv) event_add((ev), (tv)) +#define signal_set(ev, x, cb, arg) \ + event_set((ev), (x), EV_SIGNAL|EV_PERSIST, (cb), (arg)) +#define signal_del(ev) event_del(ev) +#define signal_pending(ev, tv) event_pending((ev), EV_SIGNAL, (tv)) +#define signal_initialized(ev) event_initialized(ev) +/**@}*/ + +#ifndef EVENT_FD +/* These macros are obsolete; use event_get_fd and event_get_signal instead. */ +#define EVENT_FD(ev) ((int)event_get_fd(ev)) +#define EVENT_SIGNAL(ev) event_get_signal(ev) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_EVENT_COMPAT_H_INCLUDED_ */ diff --git a/src/include/event2/event_struct.h b/src/include/event2/event_struct.h new file mode 100644 index 0000000..1c8b71b --- /dev/null +++ b/src/include/event2/event_struct.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2000-2007 Niels Provos <[email protected]> + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EVENT2_EVENT_STRUCT_H_INCLUDED_ +#define EVENT2_EVENT_STRUCT_H_INCLUDED_ + +/** @file event2/event_struct.h + + Structures used by event.h. Using these structures directly WILL harm + forward compatibility: be careful. + + No field declared in this file should be used directly in user code. Except + for historical reasons, these fields would not be exposed at all. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <event2/event-config.h> +#ifdef EVENT__HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef EVENT__HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + +/* For int types. */ +#include <event2/util.h> + +/* For evkeyvalq */ +#include <event2/keyvalq_struct.h> + +#define EVLIST_TIMEOUT 0x01 +#define EVLIST_INSERTED 0x02 +#define EVLIST_SIGNAL 0x04 +#define EVLIST_ACTIVE 0x08 +#define EVLIST_INTERNAL 0x10 +#define EVLIST_ACTIVE_LATER 0x20 +#define EVLIST_FINALIZING 0x40 +#define EVLIST_INIT 0x80 + +#define EVLIST_ALL 0xff + +/* Fix so that people don't have to run with <sys/queue.h> */ +#ifndef TAILQ_ENTRY +#define EVENT_DEFINED_TQENTRY_ +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ +} +#endif /* !TAILQ_ENTRY */ + +#ifndef TAILQ_HEAD +#define EVENT_DEFINED_TQHEAD_ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; \ + struct type **tqh_last; \ +} +#endif + +/* Fix so that people don't have to run with <sys/queue.h> */ +#ifndef LIST_ENTRY +#define EVENT_DEFINED_LISTENTRY_ +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} +#endif /* !LIST_ENTRY */ + +#ifndef LIST_HEAD +#define EVENT_DEFINED_LISTHEAD_ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ + } +#endif /* !LIST_HEAD */ + +struct event; + +struct event_callback { + TAILQ_ENTRY(event_callback) evcb_active_next; + short evcb_flags; + ev_uint8_t evcb_pri; /* smaller numbers are higher priority */ + ev_uint8_t evcb_closure; + /* allows us to adopt for different types of events */ + union { + void (*evcb_callback)(evutil_socket_t, short, void *); + void (*evcb_selfcb)(struct event_callback *, void *); + void (*evcb_evfinalize)(struct event *, void *); + void (*evcb_cbfinalize)(struct event_callback *, void *); + } evcb_cb_union; + void *evcb_arg; +}; + +struct event_base; +struct event { + struct event_callback ev_evcallback; + + /* for managing timeouts */ + union { + TAILQ_ENTRY(event) ev_next_with_common_timeout; + int min_heap_idx; + } ev_timeout_pos; + evutil_socket_t ev_fd; + + struct event_base *ev_base; + + union { + /* used for io events */ + struct { + LIST_ENTRY (event) ev_io_next; + struct timeval ev_timeout; + } ev_io; + + /* used by signal events */ + struct { + LIST_ENTRY (event) ev_signal_next; + short ev_ncalls; + /* Allows deletes in callback */ + short *ev_pncalls; + } ev_signal; + } ev_; + + short ev_events; + short ev_res; /* result passed to event callback */ + struct timeval ev_timeout; +}; + +TAILQ_HEAD (event_list, event); + +#ifdef EVENT_DEFINED_TQENTRY_ +#undef TAILQ_ENTRY +#endif + +#ifdef EVENT_DEFINED_TQHEAD_ +#undef TAILQ_HEAD +#endif + +LIST_HEAD (event_dlist, event); + +#ifdef EVENT_DEFINED_LISTENTRY_ +#undef LIST_ENTRY +#endif + +#ifdef EVENT_DEFINED_LISTHEAD_ +#undef LIST_HEAD +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_EVENT_STRUCT_H_INCLUDED_ */ diff --git a/src/include/event2/http.h b/src/include/event2/http.h new file mode 100644 index 0000000..8fb5642 --- /dev/null +++ b/src/include/event2/http.h @@ -0,0 +1,1189 @@ +/* + * Copyright (c) 2000-2007 Niels Provos <[email protected]> + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EVENT2_HTTP_H_INCLUDED_ +#define EVENT2_HTTP_H_INCLUDED_ + +/* For int types. */ +#include <event2/util.h> +#include <event2/visibility.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* In case we haven't included the right headers yet. */ +struct evbuffer; +struct event_base; +struct bufferevent; +struct evhttp_connection; + +/** @file event2/http.h + * + * Basic support for HTTP serving. + * + * As Libevent is a library for dealing with event notification and most + * interesting applications are networked today, I have often found the + * need to write HTTP code. The following prototypes and definitions provide + * an application with a minimal interface for making HTTP requests and for + * creating a very simple HTTP server. + */ + +/* Response codes */ +#define HTTP_OK 200 /**< request completed ok */ +#define HTTP_NOCONTENT 204 /**< request does not have content */ +#define HTTP_MOVEPERM 301 /**< the uri moved permanently */ +#define HTTP_MOVETEMP 302 /**< the uri moved temporarily */ +#define HTTP_NOTMODIFIED 304 /**< page was not modified from last */ +#define HTTP_BADREQUEST 400 /**< invalid http request was made */ +#define HTTP_NOTFOUND 404 /**< could not find content for uri */ +#define HTTP_BADMETHOD 405 /**< method not allowed for this uri */ +#define HTTP_ENTITYTOOLARGE 413 /**< */ +#define HTTP_EXPECTATIONFAILED 417 /**< we can't handle this expectation */ +#define HTTP_INTERNAL 500 /**< internal error */ +#define HTTP_NOTIMPLEMENTED 501 /**< not implemented */ +#define HTTP_SERVUNAVAIL 503 /**< the server is not available */ + +struct evhttp; +struct evhttp_request; +struct evkeyvalq; +struct evhttp_bound_socket; +struct evconnlistener; +struct evdns_base; + +/** + * Create a new HTTP server. + * + * @param base (optional) the event base to receive the HTTP events + * @return a pointer to a newly initialized evhttp server structure + * @see evhttp_free() + */ +EVENT2_EXPORT_SYMBOL +struct evhttp *evhttp_new(struct event_base *base); + +/** + * Binds an HTTP server on the specified address and port. + * + * Can be called multiple times to bind the same http server + * to multiple different ports. + * + * @param http a pointer to an evhttp object + * @param address a string containing the IP address to listen(2) on + * @param port the port number to listen on + * @return 0 on success, -1 on failure. + * @see evhttp_accept_socket() + */ +EVENT2_EXPORT_SYMBOL +int evhttp_bind_socket(struct evhttp *http, const char *address, ev_uint16_t port); + +/** + * Like evhttp_bind_socket(), but returns a handle for referencing the socket. + * + * The returned pointer is not valid after \a http is freed. + * + * @param http a pointer to an evhttp object + * @param address a string containing the IP address to listen(2) on + * @param port the port number to listen on + * @return Handle for the socket on success, NULL on failure. + * @see evhttp_bind_socket(), evhttp_del_accept_socket() + */ +EVENT2_EXPORT_SYMBOL +struct evhttp_bound_socket *evhttp_bind_socket_with_handle(struct evhttp *http, const char *address, ev_uint16_t port); + +/** + * Makes an HTTP server accept connections on the specified socket. + * + * This may be useful to create a socket and then fork multiple instances + * of an http server, or when a socket has been communicated via file + * descriptor passing in situations where an http servers does not have + * permissions to bind to a low-numbered port. + * + * Can be called multiple times to have the http server listen to + * multiple different sockets. + * + * @param http a pointer to an evhttp object + * @param fd a socket fd that is ready for accepting connections + * @return 0 on success, -1 on failure. + * @see evhttp_bind_socket() + */ +EVENT2_EXPORT_SYMBOL +int evhttp_accept_socket(struct evhttp *http, evutil_socket_t fd); + +/** + * Like evhttp_accept_socket(), but returns a handle for referencing the socket. + * + * The returned pointer is not valid after \a http is freed. + * + * @param http a pointer to an evhttp object + * @param fd a socket fd that is ready for accepting connections + * @return Handle for the socket on success, NULL on failure. + * @see evhttp_accept_socket(), evhttp_del_accept_socket() + */ +EVENT2_EXPORT_SYMBOL +struct evhttp_bound_socket *evhttp_accept_socket_with_handle(struct evhttp *http, evutil_socket_t fd); + +/** + * The most low-level evhttp_bind/accept method: takes an evconnlistener, and + * returns an evhttp_bound_socket. The listener will be freed when the bound + * socket is freed. + */ +EVENT2_EXPORT_SYMBOL +struct evhttp_bound_socket *evhttp_bind_listener(struct evhttp *http, struct evconnlistener *listener); + +/** + * Return the listener used to implement a bound socket. + */ +EVENT2_EXPORT_SYMBOL +struct evconnlistener *evhttp_bound_socket_get_listener(struct evhttp_bound_socket *bound); + +typedef void evhttp_bound_socket_foreach_fn(struct evhttp_bound_socket *, void *); +/** + * Applies the function specified in the first argument to all + * evhttp_bound_sockets associated with "http". The user must not + * attempt to free or remove any connections, sockets or listeners + * in the callback "function". + * + * @param http pointer to an evhttp object + * @param function function to apply to every bound socket + * @param argument pointer value passed to function for every socket iterated + */ +EVENT2_EXPORT_SYMBOL +void evhttp_foreach_bound_socket(struct evhttp *http, evhttp_bound_socket_foreach_fn *function, void *argument); + +/** + * Makes an HTTP server stop accepting connections on the specified socket + * + * This may be useful when a socket has been sent via file descriptor passing + * and is no longer needed by the current process. + * + * If you created this bound socket with evhttp_bind_socket_with_handle or + * evhttp_accept_socket_with_handle, this function closes the fd you provided. + * If you created this bound socket with evhttp_bind_listener, this function + * frees the listener you provided. + * + * \a bound_socket is an invalid pointer after this call returns. + * + * @param http a pointer to an evhttp object + * @param bound_socket a handle returned by evhttp_{bind,accept}_socket_with_handle + * @see evhttp_bind_socket_with_handle(), evhttp_accept_socket_with_handle() + */ +EVENT2_EXPORT_SYMBOL +void evhttp_del_accept_socket(struct evhttp *http, struct evhttp_bound_socket *bound_socket); + +/** + * Get the raw file descriptor referenced by an evhttp_bound_socket. + * + * @param bound_socket a handle returned by evhttp_{bind,accept}_socket_with_handle + * @return the file descriptor used by the bound socket + * @see evhttp_bind_socket_with_handle(), evhttp_accept_socket_with_handle() + */ +EVENT2_EXPORT_SYMBOL +evutil_socket_t evhttp_bound_socket_get_fd(struct evhttp_bound_socket *bound_socket); + +/** + * Free the previously created HTTP server. + * + * Works only if no requests are currently being served. + * + * @param http the evhttp server object to be freed + * @see evhttp_start() + */ +EVENT2_EXPORT_SYMBOL +void evhttp_free(struct evhttp* http); + +/** XXX Document. */ +EVENT2_EXPORT_SYMBOL +void evhttp_set_max_headers_size(struct evhttp* http, ev_ssize_t max_headers_size); +/** XXX Document. */ +EVENT2_EXPORT_SYMBOL +void evhttp_set_max_body_size(struct evhttp* http, ev_ssize_t max_body_size); + +/** + Set the value to use for the Content-Type header when none was provided. If + the content type string is NULL, the Content-Type header will not be + automatically added. + + @param http the http server on which to set the default content type + @param content_type the value for the Content-Type header +*/ +EVENT2_EXPORT_SYMBOL +void evhttp_set_default_content_type(struct evhttp *http, + const char *content_type); + +/** + Sets the what HTTP methods are supported in requests accepted by this + server, and passed to user callbacks. + + If not supported they will generate a "405 Method not allowed" response. + + By default this includes the following methods: GET, POST, HEAD, PUT, DELETE + + @param http the http server on which to set the methods + @param methods bit mask constructed from evhttp_cmd_type values +*/ +EVENT2_EXPORT_SYMBOL +void evhttp_set_allowed_methods(struct evhttp* http, ev_uint16_t methods); + +/** + Set a callback for a specified URI + + @param http the http sever on which to set the callback + @param path the path for which to invoke the callback + @param cb the callback function that gets invoked on requesting path + @param cb_arg an additional context argument for the callback + @return 0 on success, -1 if the callback existed already, -2 on failure +*/ +EVENT2_EXPORT_SYMBOL +int evhttp_set_cb(struct evhttp *http, const char *path, + void (*cb)(struct evhttp_request *, void *), void *cb_arg); + +/** Removes the callback for a specified URI */ +EVENT2_EXPORT_SYMBOL +int evhttp_del_cb(struct evhttp *, const char *); + +/** + Set a callback for all requests that are not caught by specific callbacks + + Invokes the specified callback for all requests that do not match any of + the previously specified request paths. This is catchall for requests not + specifically configured with evhttp_set_cb(). + + @param http the evhttp server object for which to set the callback + @param cb the callback to invoke for any unmatched requests + @param arg an context argument for the callback +*/ +EVENT2_EXPORT_SYMBOL +void evhttp_set_gencb(struct evhttp *http, + void (*cb)(struct evhttp_request *, void *), void *arg); + +/** + Set a callback used to create new bufferevents for connections + to a given evhttp object. + + You can use this to override the default bufferevent type -- for example, + to make this evhttp object use SSL bufferevents rather than unencrypted + ones. + + New bufferevents must be allocated with no fd set on them. + + @param http the evhttp server object for which to set the callback + @param cb the callback to invoke for incoming connections + @param arg an context argument for the callback + */ +EVENT2_EXPORT_SYMBOL +void evhttp_set_bevcb(struct evhttp *http, + struct bufferevent *(*cb)(struct event_base *, void *), void *arg); + +/** + Adds a virtual host to the http server. + + A virtual host is a newly initialized evhttp object that has request + callbacks set on it via evhttp_set_cb() or evhttp_set_gencb(). It + most not have any listing sockets associated with it. + + If the virtual host has not been removed by the time that evhttp_free() + is called on the main http server, it will be automatically freed, too. + + It is possible to have hierarchical vhosts. For example: A vhost + with the pattern *.example.com may have other vhosts with patterns + foo.example.com and bar.example.com associated with it. + + @param http the evhttp object to which to add a virtual host + @param pattern the glob pattern against which the hostname is matched. + The match is case insensitive and follows otherwise regular shell + matching. + @param vhost the virtual host to add the regular http server. + @return 0 on success, -1 on failure + @see evhttp_remove_virtual_host() +*/ +EVENT2_EXPORT_SYMBOL +int evhttp_add_virtual_host(struct evhttp* http, const char *pattern, + struct evhttp* vhost); + +/** + Removes a virtual host from the http server. + + @param http the evhttp object from which to remove the virtual host + @param vhost the virtual host to remove from the regular http server. + @return 0 on success, -1 on failure + @see evhttp_add_virtual_host() +*/ +EVENT2_EXPORT_SYMBOL +int evhttp_remove_virtual_host(struct evhttp* http, struct evhttp* vhost); + +/** + Add a server alias to an http object. The http object can be a virtual + host or the main server. + + @param http the evhttp object + @param alias the alias to add + @see evhttp_add_remove_alias() +*/ +EVENT2_EXPORT_SYMBOL +int evhttp_add_server_alias(struct evhttp *http, const char *alias); + +/** + Remove a server alias from an http object. + + @param http the evhttp object + @param alias the alias to remove + @see evhttp_add_server_alias() +*/ +EVENT2_EXPORT_SYMBOL +int evhttp_remove_server_alias(struct evhttp *http, const char *alias); + +/** + * Set the timeout for an HTTP request. + * + * @param http an evhttp object + * @param timeout_in_secs the timeout, in seconds + */ +EVENT2_EXPORT_SYMBOL +void evhttp_set_timeout(struct evhttp *http, int timeout_in_secs); + +/** + * Set the timeout for an HTTP request. + * + * @param http an evhttp object + * @param tv the timeout, or NULL + */ +EVENT2_EXPORT_SYMBOL +void evhttp_set_timeout_tv(struct evhttp *http, const struct timeval* tv); + +/* Read all the clients body, and only after this respond with an error if the + * clients body exceed max_body_size */ +#define EVHTTP_SERVER_LINGERING_CLOSE 0x0001 +/** + * Set connection flags for HTTP server. + * + * @see EVHTTP_SERVER_* + * @return 0 on success, otherwise non zero (for example if flag doesn't + * supported). + */ +EVENT2_EXPORT_SYMBOL +int evhttp_set_flags(struct evhttp *http, int flags); + +/* Request/Response functionality */ + +/** + * Send an HTML error message to the client. + * + * @param req a request object + * @param error the HTTP error code + * @param reason a brief explanation of the error. If this is NULL, we'll + * just use the standard meaning of the error code. + */ +EVENT2_EXPORT_SYMBOL +void evhttp_send_error(struct evhttp_request *req, int error, + const char *reason); + +/** + * Send an HTML reply to the client. + * + * The body of the reply consists of the data in databuf. After calling + * evhttp_send_reply() databuf will be empty, but the buffer is still + * owned by the caller and needs to be deallocated by the caller if + * necessary. + * + * @param req a request object + * @param code the HTTP response code to send + * @param reason a brief message to send with the response code + * @param databuf the body of the response + */ +EVENT2_EXPORT_SYMBOL +void evhttp_send_reply(struct evhttp_request *req, int code, + const char *reason, struct evbuffer *databuf); + +/* Low-level response interface, for streaming/chunked replies */ + +/** + Initiate a reply that uses Transfer-Encoding chunked. + + This allows the caller to stream the reply back to the client and is + useful when either not all of the reply data is immediately available + or when sending very large replies. + + The caller needs to supply data chunks with evhttp_send_reply_chunk() + and complete the reply by calling evhttp_send_reply_end(). + + @param req a request object + @param code the HTTP response code to send + @param reason a brief message to send with the response code +*/ +EVENT2_EXPORT_SYMBOL +void evhttp_send_reply_start(struct evhttp_request *req, int code, + const char *reason); + +/** + Send another data chunk as part of an ongoing chunked reply. + + The reply chunk consists of the data in databuf. After calling + evhttp_send_reply_chunk() databuf will be empty, but the buffer is + still owned by the caller and needs to be deallocated by the caller + if necessary. + + @param req a request object + @param databuf the data chunk to send as part of the reply. +*/ +EVENT2_EXPORT_SYMBOL +void evhttp_send_reply_chunk(struct evhttp_request *req, + struct evbuffer *databuf); + +/** + Send another data chunk as part of an ongoing chunked reply. + + The reply chunk consists of the data in databuf. After calling + evhttp_send_reply_chunk() databuf will be empty, but the buffer is + still owned by the caller and needs to be deallocated by the caller + if necessary. + + @param req a request object + @param databuf the data chunk to send as part of the reply. + @param cb callback funcion + @param call back's argument. +*/ +EVENT2_EXPORT_SYMBOL +void evhttp_send_reply_chunk_with_cb(struct evhttp_request *, struct evbuffer *, + void (*cb)(struct evhttp_connection *, void *), void *arg); + +/** + Complete a chunked reply, freeing the request as appropriate. + + @param req a request object +*/ +EVENT2_EXPORT_SYMBOL +void evhttp_send_reply_end(struct evhttp_request *req); + +/* + * Interfaces for making requests + */ + +/** The different request types supported by evhttp. These are as specified + * in RFC2616, except for PATCH which is specified by RFC5789. + * + * By default, only some of these methods are accepted and passed to user + * callbacks; use evhttp_set_allowed_methods() to change which methods + * are allowed. + */ +enum evhttp_cmd_type { + EVHTTP_REQ_GET = 1 << 0, + EVHTTP_REQ_POST = 1 << 1, + EVHTTP_REQ_HEAD = 1 << 2, + EVHTTP_REQ_PUT = 1 << 3, + EVHTTP_REQ_DELETE = 1 << 4, + EVHTTP_REQ_OPTIONS = 1 << 5, + EVHTTP_REQ_TRACE = 1 << 6, + EVHTTP_REQ_CONNECT = 1 << 7, + EVHTTP_REQ_PATCH = 1 << 8 +}; + +/** a request object can represent either a request or a reply */ +enum evhttp_request_kind { EVHTTP_REQUEST, EVHTTP_RESPONSE }; + +/** + * Create and return a connection object that can be used to for making HTTP + * requests. The connection object tries to resolve address and establish the + * connection when it is given an http request object. + * + * @param base the event_base to use for handling the connection + * @param dnsbase the dns_base to use for resolving host names; if not + * specified host name resolution will block. + * @param bev a bufferevent to use for connecting to the server; if NULL, a + * socket-based bufferevent will be created. This buffrevent will be freed + * when the connection closes. It must have no fd set on it. + * @param address the address to which to connect + * @param port the port to connect to + * @return an evhttp_connection object that can be used for making requests + */ +EVENT2_EXPORT_SYMBOL +struct evhttp_connection *evhttp_connection_base_bufferevent_new( + struct event_base *base, struct evdns_base *dnsbase, struct bufferevent* bev, const char *address, ev_uint16_t port); + +/** + * Return the bufferevent that an evhttp_connection is using. + */ +EVENT2_EXPORT_SYMBOL +struct bufferevent* evhttp_connection_get_bufferevent(struct evhttp_connection *evcon); + +/** + * Return the HTTP server associated with this connection, or NULL. + */ +EVENT2_EXPORT_SYMBOL +struct evhttp *evhttp_connection_get_server(struct evhttp_connection *evcon); + +/** + * Creates a new request object that needs to be filled in with the request + * parameters. The callback is executed when the request completed or an + * error occurred. + */ +EVENT2_EXPORT_SYMBOL +struct evhttp_request *evhttp_request_new( + void (*cb)(struct evhttp_request *, void *), void *arg); + +/** + * Enable delivery of chunks to requestor. + * @param cb will be called after every read of data with the same argument + * as the completion callback. Will never be called on an empty + * response. May drain the input buffer; it will be drained + * automatically on return. + */ +EVENT2_EXPORT_SYMBOL +void evhttp_request_set_chunked_cb(struct evhttp_request *, + void (*cb)(struct evhttp_request *, void *)); + +/** + * Register callback for additional parsing of request headers. + * @param cb will be called after receiving and parsing the full header. + * It allows analyzing the header and possibly closing the connection + * by returning a value < 0. + */ +EVENT2_EXPORT_SYMBOL +void evhttp_request_set_header_cb(struct evhttp_request *, + int (*cb)(struct evhttp_request *, void *)); + +/** + * The different error types supported by evhttp + * + * @see evhttp_request_set_error_cb() + */ +enum evhttp_request_error { + /** + * Timeout reached, also @see evhttp_connection_set_timeout() + */ + EVREQ_HTTP_TIMEOUT, + /** + * EOF reached + */ + EVREQ_HTTP_EOF, + /** + * Error while reading header, or invalid header + */ + EVREQ_HTTP_INVALID_HEADER, + /** + * Error encountered while reading or writing + */ + EVREQ_HTTP_BUFFER_ERROR, + /** + * The evhttp_cancel_request() called on this request. + */ + EVREQ_HTTP_REQUEST_CANCEL, + /** + * Body is greater then evhttp_connection_set_max_body_size() + */ + EVREQ_HTTP_DATA_TOO_LONG +}; +/** + * Set a callback for errors + * @see evhttp_request_error for error types. + * + * On error, both the error callback and the regular callback will be called, + * error callback is called before the regular callback. + **/ +EVENT2_EXPORT_SYMBOL +void evhttp_request_set_error_cb(struct evhttp_request *, + void (*)(enum evhttp_request_error, void *)); + +/** + * Set a callback to be called on request completion of evhttp_send_* function. + * + * The callback function will be called on the completion of the request after + * the output data has been written and before the evhttp_request object + * is destroyed. This can be useful for tracking resources associated with a + * request (ex: timing metrics). + * + * @param req a request object + * @param cb callback function that will be called on request completion + * @param cb_arg an additional context argument for the callback + */ +EVENT2_EXPORT_SYMBOL +void evhttp_request_set_on_complete_cb(struct evhttp_request *req, + void (*cb)(struct evhttp_request *, void *), void *cb_arg); + +/** Frees the request object and removes associated events. */ +EVENT2_EXPORT_SYMBOL +void evhttp_request_free(struct evhttp_request *req); + +/** + * Create and return a connection object that can be used to for making HTTP + * requests. The connection object tries to resolve address and establish the + * connection when it is given an http request object. + * + * @param base the event_base to use for handling the connection + * @param dnsbase the dns_base to use for resolving host names; if not + * specified host name resolution will block. + * @param address the address to which to connect + * @param port the port to connect to + * @return an evhttp_connection object that can be used for making requests + */ +EVENT2_EXPORT_SYMBOL +struct evhttp_connection *evhttp_connection_base_new( + struct event_base *base, struct evdns_base *dnsbase, + const char *address, ev_uint16_t port); + +/** + * Set family hint for DNS requests. + */ +EVENT2_EXPORT_SYMBOL +void evhttp_connection_set_family(struct evhttp_connection *evcon, + int family); + +/* reuse connection address on retry */ +#define EVHTTP_CON_REUSE_CONNECTED_ADDR 0x0008 +/* Try to read error, since server may already send and close + * connection, but if at that time we have some data to send then we + * can send get EPIPE and fail, while we can read that HTTP error. */ +#define EVHTTP_CON_READ_ON_WRITE_ERROR 0x0010 +/* @see EVHTTP_SERVER_LINGERING_CLOSE */ +#define EVHTTP_CON_LINGERING_CLOSE 0x0020 +/* Padding for public flags, @see EVHTTP_CON_* in http-internal.h */ +#define EVHTTP_CON_PUBLIC_FLAGS_END 0x100000 +/** + * Set connection flags. + * + * @see EVHTTP_CON_* + * @return 0 on success, otherwise non zero (for example if flag doesn't + * supported). + */ +EVENT2_EXPORT_SYMBOL +int evhttp_connection_set_flags(struct evhttp_connection *evcon, + int flags); + +/** Takes ownership of the request object + * + * Can be used in a request callback to keep onto the request until + * evhttp_request_free() is explicitly called by the user. + */ +EVENT2_EXPORT_SYMBOL +void evhttp_request_own(struct evhttp_request *req); + +/** Returns 1 if the request is owned by the user */ +EVENT2_EXPORT_SYMBOL +int evhttp_request_is_owned(struct evhttp_request *req); + +/** + * Returns the connection object associated with the request or NULL + * + * The user needs to either free the request explicitly or call + * evhttp_send_reply_end(). + */ +EVENT2_EXPORT_SYMBOL +struct evhttp_connection *evhttp_request_get_connection(struct evhttp_request *req); + +/** + * Returns the underlying event_base for this connection + */ +EVENT2_EXPORT_SYMBOL +struct event_base *evhttp_connection_get_base(struct evhttp_connection *req); + +EVENT2_EXPORT_SYMBOL +void evhttp_connection_set_max_headers_size(struct evhttp_connection *evcon, + ev_ssize_t new_max_headers_size); + +EVENT2_EXPORT_SYMBOL +void evhttp_connection_set_max_body_size(struct evhttp_connection* evcon, + ev_ssize_t new_max_body_size); + +/** Frees an http connection */ +EVENT2_EXPORT_SYMBOL +void evhttp_connection_free(struct evhttp_connection *evcon); + +/** Disowns a given connection object + * + * Can be used to tell libevent to free the connection object after + * the last request has completed or failed. + */ +EVENT2_EXPORT_SYMBOL +void evhttp_connection_free_on_completion(struct evhttp_connection *evcon); + +/** sets the ip address from which http connections are made */ +EVENT2_EXPORT_SYMBOL +void evhttp_connection_set_local_address(struct evhttp_connection *evcon, + const char *address); + +/** sets the local port from which http connections are made */ +EVENT2_EXPORT_SYMBOL +void evhttp_connection_set_local_port(struct evhttp_connection *evcon, + ev_uint16_t port); + +/** Sets the timeout in seconds for events related to this connection */ +EVENT2_EXPORT_SYMBOL +void evhttp_connection_set_timeout(struct evhttp_connection *evcon, + int timeout_in_secs); + +/** Sets the timeout for events related to this connection. Takes a struct + * timeval. */ +EVENT2_EXPORT_SYMBOL +void evhttp_connection_set_timeout_tv(struct evhttp_connection *evcon, + const struct timeval *tv); + +/** Sets the delay before retrying requests on this connection. This is only + * used if evhttp_connection_set_retries is used to make the number of retries + * at least one. Each retry after the first is twice as long as the one before + * it. */ +EVENT2_EXPORT_SYMBOL +void evhttp_connection_set_initial_retry_tv(struct evhttp_connection *evcon, + const struct timeval *tv); + +/** Sets the retry limit for this connection - -1 repeats indefinitely */ +EVENT2_EXPORT_SYMBOL +void evhttp_connection_set_retries(struct evhttp_connection *evcon, + int retry_max); + +/** Set a callback for connection close. */ +EVENT2_EXPORT_SYMBOL +void evhttp_connection_set_closecb(struct evhttp_connection *evcon, + void (*)(struct evhttp_connection *, void *), void *); + +/** Get the remote address and port associated with this connection. */ +EVENT2_EXPORT_SYMBOL +void evhttp_connection_get_peer(struct evhttp_connection *evcon, + char **address, ev_uint16_t *port); + +/** Get the remote address associated with this connection. + * extracted from getpeername() OR from nameserver. + * + * @return NULL if getpeername() return non success, + * or connection is not connected, + * otherwise it return pointer to struct sockaddr_storage */ +EVENT2_EXPORT_SYMBOL +const struct sockaddr* +evhttp_connection_get_addr(struct evhttp_connection *evcon); + +/** + Make an HTTP request over the specified connection. + + The connection gets ownership of the request. On failure, the + request object is no longer valid as it has been freed. + + @param evcon the evhttp_connection object over which to send the request + @param req the previously created and configured request object + @param type the request type EVHTTP_REQ_GET, EVHTTP_REQ_POST, etc. + @param uri the URI associated with the request + @return 0 on success, -1 on failure + @see evhttp_cancel_request() +*/ +EVENT2_EXPORT_SYMBOL +int evhttp_make_request(struct evhttp_connection *evcon, + struct evhttp_request *req, + enum evhttp_cmd_type type, const char *uri); + +/** + Cancels a pending HTTP request. + + Cancels an ongoing HTTP request. The callback associated with this request + is not executed and the request object is freed. If the request is + currently being processed, e.g. it is ongoing, the corresponding + evhttp_connection object is going to get reset. + + A request cannot be canceled if its callback has executed already. A request + may be canceled reentrantly from its chunked callback. + + @param req the evhttp_request to cancel; req becomes invalid after this call. +*/ +EVENT2_EXPORT_SYMBOL +void evhttp_cancel_request(struct evhttp_request *req); + +/** + * A structure to hold a parsed URI or Relative-Ref conforming to RFC3986. + */ +struct evhttp_uri; + +/** Returns the request URI */ +EVENT2_EXPORT_SYMBOL +const char *evhttp_request_get_uri(const struct evhttp_request *req); +/** Returns the request URI (parsed) */ +EVENT2_EXPORT_SYMBOL +const struct evhttp_uri *evhttp_request_get_evhttp_uri(const struct evhttp_request *req); +/** Returns the request command */ +EVENT2_EXPORT_SYMBOL +enum evhttp_cmd_type evhttp_request_get_command(const struct evhttp_request *req); + +EVENT2_EXPORT_SYMBOL +int evhttp_request_get_response_code(const struct evhttp_request *req); +EVENT2_EXPORT_SYMBOL +const char * evhttp_request_get_response_code_line(const struct evhttp_request *req); + +/** Returns the input headers */ +EVENT2_EXPORT_SYMBOL +struct evkeyvalq *evhttp_request_get_input_headers(struct evhttp_request *req); +/** Returns the output headers */ +EVENT2_EXPORT_SYMBOL +struct evkeyvalq *evhttp_request_get_output_headers(struct evhttp_request *req); +/** Returns the input buffer */ +EVENT2_EXPORT_SYMBOL +struct evbuffer *evhttp_request_get_input_buffer(struct evhttp_request *req); +/** Returns the output buffer */ +EVENT2_EXPORT_SYMBOL +struct evbuffer *evhttp_request_get_output_buffer(struct evhttp_request *req); +/** Returns the host associated with the request. If a client sends an absolute + URI, the host part of that is preferred. Otherwise, the input headers are + searched for a Host: header. NULL is returned if no absolute URI or Host: + header is provided. */ +EVENT2_EXPORT_SYMBOL +const char *evhttp_request_get_host(struct evhttp_request *req); + +/* Interfaces for dealing with HTTP headers */ + +/** + Finds the value belonging to a header. + + @param headers the evkeyvalq object in which to find the header + @param key the name of the header to find + @returns a pointer to the value for the header or NULL if the header + could not be found. + @see evhttp_add_header(), evhttp_remove_header() +*/ +EVENT2_EXPORT_SYMBOL +const char *evhttp_find_header(const struct evkeyvalq *headers, + const char *key); + +/** + Removes a header from a list of existing headers. + + @param headers the evkeyvalq object from which to remove a header + @param key the name of the header to remove + @returns 0 if the header was removed, -1 otherwise. + @see evhttp_find_header(), evhttp_add_header() +*/ +EVENT2_EXPORT_SYMBOL +int evhttp_remove_header(struct evkeyvalq *headers, const char *key); + +/** + Adds a header to a list of existing headers. + + @param headers the evkeyvalq object to which to add a header + @param key the name of the header + @param value the value belonging to the header + @returns 0 on success, -1 otherwise. + @see evhttp_find_header(), evhttp_clear_headers() +*/ +EVENT2_EXPORT_SYMBOL +int evhttp_add_header(struct evkeyvalq *headers, const char *key, const char *value); + +/** + Removes all headers from the header list. + + @param headers the evkeyvalq object from which to remove all headers +*/ +EVENT2_EXPORT_SYMBOL +void evhttp_clear_headers(struct evkeyvalq *headers); + +/* Miscellaneous utility functions */ + + +/** + Helper function to encode a string for inclusion in a URI. All + characters are replaced by their hex-escaped (%22) equivalents, + except for characters explicitly unreserved by RFC3986 -- that is, + ASCII alphanumeric characters, hyphen, dot, underscore, and tilde. + + The returned string must be freed by the caller. + + @param str an unencoded string + @return a newly allocated URI-encoded string or NULL on failure + */ +EVENT2_EXPORT_SYMBOL +char *evhttp_encode_uri(const char *str); + +/** + As evhttp_encode_uri, but if 'size' is nonnegative, treat the string + as being 'size' bytes long. This allows you to encode strings that + may contain 0-valued bytes. + + The returned string must be freed by the caller. + + @param str an unencoded string + @param size the length of the string to encode, or -1 if the string + is NUL-terminated + @param space_to_plus if true, space characters in 'str' are encoded + as +, not %20. + @return a newly allocate URI-encoded string, or NULL on failure. + */ +EVENT2_EXPORT_SYMBOL +char *evhttp_uriencode(const char *str, ev_ssize_t size, int space_to_plus); + +/** + Helper function to sort of decode a URI-encoded string. Unlike + evhttp_get_decoded_uri, it decodes all plus characters that appear + _after_ the first question mark character, but no plusses that occur + before. This is not a good way to decode URIs in whole or in part. + + The returned string must be freed by the caller + + @deprecated This function is deprecated; you probably want to use + evhttp_get_decoded_uri instead. + + @param uri an encoded URI + @return a newly allocated unencoded URI or NULL on failure + */ +EVENT2_EXPORT_SYMBOL +char *evhttp_decode_uri(const char *uri); + +/** + Helper function to decode a URI-escaped string or HTTP parameter. + + If 'decode_plus' is 1, then we decode the string as an HTTP parameter + value, and convert all plus ('+') characters to spaces. If + 'decode_plus' is 0, we leave all plus characters unchanged. + + The returned string must be freed by the caller. + + @param uri a URI-encode encoded URI + @param decode_plus determines whether we convert '+' to space. + @param size_out if size_out is not NULL, *size_out is set to the size of the + returned string + @return a newly allocated unencoded URI or NULL on failure + */ +EVENT2_EXPORT_SYMBOL +char *evhttp_uridecode(const char *uri, int decode_plus, + size_t *size_out); + +/** + Helper function to parse out arguments in a query. + + Parsing a URI like + + http://foo.com/?q=test&s=some+thing + + will result in two entries in the key value queue. + + The first entry is: key="q", value="test" + The second entry is: key="s", value="some thing" + + @deprecated This function is deprecated as of Libevent 2.0.9. Use + evhttp_uri_parse and evhttp_parse_query_str instead. + + @param uri the request URI + @param headers the head of the evkeyval queue + @return 0 on success, -1 on failure + */ +EVENT2_EXPORT_SYMBOL +int evhttp_parse_query(const char *uri, struct evkeyvalq *headers); + +/** + Helper function to parse out arguments from the query portion of an + HTTP URI. + + Parsing a query string like + + q=test&s=some+thing + + will result in two entries in the key value queue. + + The first entry is: key="q", value="test" + The second entry is: key="s", value="some thing" + + @param query_parse the query portion of the URI + @param headers the head of the evkeyval queue + @return 0 on success, -1 on failure + */ +EVENT2_EXPORT_SYMBOL +int evhttp_parse_query_str(const char *uri, struct evkeyvalq *headers); + +/** + * Escape HTML character entities in a string. + * + * Replaces <, >, ", ' and & with <, >, ", + * ' and & correspondingly. + * + * The returned string needs to be freed by the caller. + * + * @param html an unescaped HTML string + * @return an escaped HTML string or NULL on error + */ +EVENT2_EXPORT_SYMBOL +char *evhttp_htmlescape(const char *html); + +/** + * Return a new empty evhttp_uri with no fields set. + */ +EVENT2_EXPORT_SYMBOL +struct evhttp_uri *evhttp_uri_new(void); + +/** + * Changes the flags set on a given URI. See EVHTTP_URI_* for + * a list of flags. + **/ +EVENT2_EXPORT_SYMBOL +void evhttp_uri_set_flags(struct evhttp_uri *uri, unsigned flags); + +/** Return the scheme of an evhttp_uri, or NULL if there is no scheme has + * been set and the evhttp_uri contains a Relative-Ref. */ +EVENT2_EXPORT_SYMBOL +const char *evhttp_uri_get_scheme(const struct evhttp_uri *uri); +/** + * Return the userinfo part of an evhttp_uri, or NULL if it has no userinfo + * set. + */ +EVENT2_EXPORT_SYMBOL +const char *evhttp_uri_get_userinfo(const struct evhttp_uri *uri); +/** + * Return the host part of an evhttp_uri, or NULL if it has no host set. + * The host may either be a regular hostname (conforming to the RFC 3986 + * "regname" production), or an IPv4 address, or the empty string, or a + * bracketed IPv6 address, or a bracketed 'IP-Future' address. + * + * Note that having a NULL host means that the URI has no authority + * section, but having an empty-string host means that the URI has an + * authority section with no host part. For example, + * "mailto:[email protected]" has a host of NULL, but "file:///etc/motd" + * has a host of "". + */ +EVENT2_EXPORT_SYMBOL +const char *evhttp_uri_get_host(const struct evhttp_uri *uri); +/** Return the port part of an evhttp_uri, or -1 if there is no port set. */ +EVENT2_EXPORT_SYMBOL +int evhttp_uri_get_port(const struct evhttp_uri *uri); +/** Return the path part of an evhttp_uri, or NULL if it has no path set */ +EVENT2_EXPORT_SYMBOL +const char *evhttp_uri_get_path(const struct evhttp_uri *uri); +/** Return the query part of an evhttp_uri (excluding the leading "?"), or + * NULL if it has no query set */ +EVENT2_EXPORT_SYMBOL +const char *evhttp_uri_get_query(const struct evhttp_uri *uri); +/** Return the fragment part of an evhttp_uri (excluding the leading "#"), + * or NULL if it has no fragment set */ +EVENT2_EXPORT_SYMBOL +const char *evhttp_uri_get_fragment(const struct evhttp_uri *uri); + +/** Set the scheme of an evhttp_uri, or clear the scheme if scheme==NULL. + * Returns 0 on success, -1 if scheme is not well-formed. */ +EVENT2_EXPORT_SYMBOL +int evhttp_uri_set_scheme(struct evhttp_uri *uri, const char *scheme); +/** Set the userinfo of an evhttp_uri, or clear the userinfo if userinfo==NULL. + * Returns 0 on success, -1 if userinfo is not well-formed. */ +EVENT2_EXPORT_SYMBOL +int evhttp_uri_set_userinfo(struct evhttp_uri *uri, const char *userinfo); +/** Set the host of an evhttp_uri, or clear the host if host==NULL. + * Returns 0 on success, -1 if host is not well-formed. */ +EVENT2_EXPORT_SYMBOL +int evhttp_uri_set_host(struct evhttp_uri *uri, const char *host); +/** Set the port of an evhttp_uri, or clear the port if port==-1. + * Returns 0 on success, -1 if port is not well-formed. */ +EVENT2_EXPORT_SYMBOL +int evhttp_uri_set_port(struct evhttp_uri *uri, int port); +/** Set the path of an evhttp_uri, or clear the path if path==NULL. + * Returns 0 on success, -1 if path is not well-formed. */ +EVENT2_EXPORT_SYMBOL +int evhttp_uri_set_path(struct evhttp_uri *uri, const char *path); +/** Set the query of an evhttp_uri, or clear the query if query==NULL. + * The query should not include a leading "?". + * Returns 0 on success, -1 if query is not well-formed. */ +EVENT2_EXPORT_SYMBOL +int evhttp_uri_set_query(struct evhttp_uri *uri, const char *query); +/** Set the fragment of an evhttp_uri, or clear the fragment if fragment==NULL. + * The fragment should not include a leading "#". + * Returns 0 on success, -1 if fragment is not well-formed. */ +EVENT2_EXPORT_SYMBOL +int evhttp_uri_set_fragment(struct evhttp_uri *uri, const char *fragment); + +/** + * Helper function to parse a URI-Reference as specified by RFC3986. + * + * This function matches the URI-Reference production from RFC3986, + * which includes both URIs like + * + * scheme://[[userinfo]@]foo.com[:port]]/[path][?query][#fragment] + * + * and relative-refs like + * + * [path][?query][#fragment] + * + * Any optional elements portions not present in the original URI are + * left set to NULL in the resulting evhttp_uri. If no port is + * specified, the port is set to -1. + * + * Note that no decoding is performed on percent-escaped characters in + * the string; if you want to parse them, use evhttp_uridecode or + * evhttp_parse_query_str as appropriate. + * + * Note also that most URI schemes will have additional constraints that + * this function does not know about, and cannot check. For example, + * mailto://www.example.com/cgi-bin/fortune.pl is not a reasonable + * mailto url, http://www.example.com:99999/ is not a reasonable HTTP + * URL, and ftp:[email protected] is not a reasonable FTP URL. + * Nevertheless, all of these URLs conform to RFC3986, and this function + * accepts all of them as valid. + * + * @param source_uri the request URI + * @param flags Zero or more EVHTTP_URI_* flags to affect the behavior + * of the parser. + * @return uri container to hold parsed data, or NULL if there is error + * @see evhttp_uri_free() + */ +EVENT2_EXPORT_SYMBOL +struct evhttp_uri *evhttp_uri_parse_with_flags(const char *source_uri, + unsigned flags); + +/** Tolerate URIs that do not conform to RFC3986. + * + * Unfortunately, some HTTP clients generate URIs that, according to RFC3986, + * are not conformant URIs. If you need to support these URIs, you can + * do so by passing this flag to evhttp_uri_parse_with_flags. + * + * Currently, these changes are: + * <ul> + * <li> Nonconformant URIs are allowed to contain otherwise unreasonable + * characters in their path, query, and fragment components. + * </ul> + */ +#define EVHTTP_URI_NONCONFORMANT 0x01 + +/** Alias for evhttp_uri_parse_with_flags(source_uri, 0) */ +EVENT2_EXPORT_SYMBOL +struct evhttp_uri *evhttp_uri_parse(const char *source_uri); + +/** + * Free all memory allocated for a parsed uri. Only use this for URIs + * generated by evhttp_uri_parse. + * + * @param uri container with parsed data + * @see evhttp_uri_parse() + */ +EVENT2_EXPORT_SYMBOL +void evhttp_uri_free(struct evhttp_uri *uri); + +/** + * Join together the uri parts from parsed data to form a URI-Reference. + * + * Note that no escaping of reserved characters is done on the members + * of the evhttp_uri, so the generated string might not be a valid URI + * unless the members of evhttp_uri are themselves valid. + * + * @param uri container with parsed data + * @param buf destination buffer + * @param limit destination buffer size + * @return an joined uri as string or NULL on error + * @see evhttp_uri_parse() + */ +EVENT2_EXPORT_SYMBOL +char *evhttp_uri_join(struct evhttp_uri *uri, char *buf, size_t limit); + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_HTTP_H_INCLUDED_ */ diff --git a/src/include/event2/http_compat.h b/src/include/event2/http_compat.h new file mode 100644 index 0000000..43c2c43 --- /dev/null +++ b/src/include/event2/http_compat.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2000-2007 Niels Provos <[email protected]> + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EVENT2_HTTP_COMPAT_H_INCLUDED_ +#define EVENT2_HTTP_COMPAT_H_INCLUDED_ + +/** @file event2/http_compat.h + + Potentially non-threadsafe versions of the functions in http.h: provided + only for backwards compatibility. + + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <event2/event-config.h> +#ifdef EVENT__HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef EVENT__HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + +/* For int types. */ +#include <event2/util.h> + +/** + * Start an HTTP server on the specified address and port + * + * @deprecated It does not allow an event base to be specified + * + * @param address the address to which the HTTP server should be bound + * @param port the port number on which the HTTP server should listen + * @return an struct evhttp object + */ +struct evhttp *evhttp_start(const char *address, ev_uint16_t port); + +/** + * A connection object that can be used to for making HTTP requests. The + * connection object tries to establish the connection when it is given an + * http request object. + * + * @deprecated It does not allow an event base to be specified + */ +struct evhttp_connection *evhttp_connection_new( + const char *address, ev_uint16_t port); + +/** + * Associates an event base with the connection - can only be called + * on a freshly created connection object that has not been used yet. + * + * @deprecated XXXX Why? + */ +void evhttp_connection_set_base(struct evhttp_connection *evcon, + struct event_base *base); + + +/** Returns the request URI */ +#define evhttp_request_uri evhttp_request_get_uri + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_EVENT_COMPAT_H_INCLUDED_ */ diff --git a/src/include/event2/http_struct.h b/src/include/event2/http_struct.h new file mode 100644 index 0000000..4bf5b1f --- /dev/null +++ b/src/include/event2/http_struct.h @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2000-2007 Niels Provos <[email protected]> + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EVENT2_HTTP_STRUCT_H_INCLUDED_ +#define EVENT2_HTTP_STRUCT_H_INCLUDED_ + +/** @file event2/http_struct.h + + Data structures for http. Using these structures may hurt forward + compatibility with later versions of Libevent: be careful! + + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <event2/event-config.h> +#ifdef EVENT__HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef EVENT__HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + +/* For int types. */ +#include <event2/util.h> + +/** + * the request structure that a server receives. + * WARNING: expect this structure to change. I will try to provide + * reasonable accessors. + */ +struct evhttp_request { +#if defined(TAILQ_ENTRY) + TAILQ_ENTRY(evhttp_request) next; +#else +struct { + struct evhttp_request *tqe_next; + struct evhttp_request **tqe_prev; +} next; +#endif + + /* the connection object that this request belongs to */ + struct evhttp_connection *evcon; + int flags; +/** The request obj owns the evhttp connection and needs to free it */ +#define EVHTTP_REQ_OWN_CONNECTION 0x0001 +/** Request was made via a proxy */ +#define EVHTTP_PROXY_REQUEST 0x0002 +/** The request object is owned by the user; the user must free it */ +#define EVHTTP_USER_OWNED 0x0004 +/** The request will be used again upstack; freeing must be deferred */ +#define EVHTTP_REQ_DEFER_FREE 0x0008 +/** The request should be freed upstack */ +#define EVHTTP_REQ_NEEDS_FREE 0x0010 + + struct evkeyvalq *input_headers; + struct evkeyvalq *output_headers; + + /* address of the remote host and the port connection came from */ + char *remote_host; + ev_uint16_t remote_port; + + /* cache of the hostname for evhttp_request_get_host */ + char *host_cache; + + enum evhttp_request_kind kind; + enum evhttp_cmd_type type; + + size_t headers_size; + size_t body_size; + + char *uri; /* uri after HTTP request was parsed */ + struct evhttp_uri *uri_elems; /* uri elements */ + + char major; /* HTTP Major number */ + char minor; /* HTTP Minor number */ + + int response_code; /* HTTP Response code */ + char *response_code_line; /* Readable response */ + + struct evbuffer *input_buffer; /* read data */ + ev_int64_t ntoread; + unsigned chunked:1, /* a chunked request */ + userdone:1; /* the user has sent all data */ + + struct evbuffer *output_buffer; /* outgoing post or data */ + + /* Callback */ + void (*cb)(struct evhttp_request *, void *); + void *cb_arg; + + /* + * Chunked data callback - call for each completed chunk if + * specified. If not specified, all the data is delivered via + * the regular callback. + */ + void (*chunk_cb)(struct evhttp_request *, void *); + + /* + * Callback added for forked-daapd so they can collect ICY + * (shoutcast) metadata from the http header. If return + * int is negative the connection will be closed. + */ + int (*header_cb)(struct evhttp_request *, void *); + + /* + * Error callback - called when error is occured. + * @see evhttp_request_error for error types. + * + * @see evhttp_request_set_error_cb() + */ + void (*error_cb)(enum evhttp_request_error, void *); + + /* + * Send complete callback - called when the request is actually + * sent and completed. + */ + void (*on_complete_cb)(struct evhttp_request *, void *); + void *on_complete_cb_arg; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_HTTP_STRUCT_H_INCLUDED_ */ + diff --git a/src/include/event2/keyvalq_struct.h b/src/include/event2/keyvalq_struct.h new file mode 100644 index 0000000..bffa54b --- /dev/null +++ b/src/include/event2/keyvalq_struct.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2000-2007 Niels Provos <[email protected]> + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EVENT2_KEYVALQ_STRUCT_H_INCLUDED_ +#define EVENT2_KEYVALQ_STRUCT_H_INCLUDED_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Fix so that people don't have to run with <sys/queue.h> */ +/* XXXX This code is duplicated with event_struct.h */ +#ifndef TAILQ_ENTRY +#define EVENT_DEFINED_TQENTRY_ +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ +} +#endif /* !TAILQ_ENTRY */ + +#ifndef TAILQ_HEAD +#define EVENT_DEFINED_TQHEAD_ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; \ + struct type **tqh_last; \ +} +#endif + +/* + * Key-Value pairs. Can be used for HTTP headers but also for + * query argument parsing. + */ +struct evkeyval { + TAILQ_ENTRY(evkeyval) next; + + char *key; + char *value; +}; + +TAILQ_HEAD (evkeyvalq, evkeyval); + +/* XXXX This code is duplicated with event_struct.h */ +#ifdef EVENT_DEFINED_TQENTRY_ +#undef TAILQ_ENTRY +#endif + +#ifdef EVENT_DEFINED_TQHEAD_ +#undef TAILQ_HEAD +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/include/event2/listener.h b/src/include/event2/listener.h new file mode 100644 index 0000000..84b4da0 --- /dev/null +++ b/src/include/event2/listener.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2000-2007 Niels Provos <[email protected]> + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EVENT2_LISTENER_H_INCLUDED_ +#define EVENT2_LISTENER_H_INCLUDED_ + +#include <event2/visibility.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#include <event2/event.h> + +struct sockaddr; +struct evconnlistener; + +/** + A callback that we invoke when a listener has a new connection. + + @param listener The evconnlistener + @param fd The new file descriptor + @param addr The source address of the connection + @param socklen The length of addr + @param user_arg the pointer passed to evconnlistener_new() + */ +typedef void (*evconnlistener_cb)(struct evconnlistener *, evutil_socket_t, struct sockaddr *, int socklen, void *); + +/** + A callback that we invoke when a listener encounters a non-retriable error. + + @param listener The evconnlistener + @param user_arg the pointer passed to evconnlistener_new() + */ +typedef void (*evconnlistener_errorcb)(struct evconnlistener *, void *); + +/** Flag: Indicates that we should not make incoming sockets nonblocking + * before passing them to the callback. */ +#define LEV_OPT_LEAVE_SOCKETS_BLOCKING (1u<<0) +/** Flag: Indicates that freeing the listener should close the underlying + * socket. */ +#define LEV_OPT_CLOSE_ON_FREE (1u<<1) +/** Flag: Indicates that we should set the close-on-exec flag, if possible */ +#define LEV_OPT_CLOSE_ON_EXEC (1u<<2) +/** Flag: Indicates that we should disable the timeout (if any) between when + * this socket is closed and when we can listen again on the same port. */ +#define LEV_OPT_REUSEABLE (1u<<3) +/** Flag: Indicates that the listener should be locked so it's safe to use + * from multiple threadcs at once. */ +#define LEV_OPT_THREADSAFE (1u<<4) +/** Flag: Indicates that the listener should be created in disabled + * state. Use evconnlistener_enable() to enable it later. */ +#define LEV_OPT_DISABLED (1u<<5) +/** Flag: Indicates that the listener should defer accept() until data is + * available, if possible. Ignored on platforms that do not support this. + * + * This option can help performance for protocols where the client transmits + * immediately after connecting. Do not use this option if your protocol + * _doesn't_ start out with the client transmitting data, since in that case + * this option will sometimes cause the kernel to never tell you about the + * connection. + * + * This option is only supported by evconnlistener_new_bind(): it can't + * work with evconnlistener_new_fd(), since the listener needs to be told + * to use the option before it is actually bound. + */ +#define LEV_OPT_DEFERRED_ACCEPT (1u<<6) +/** Flag: Indicates that we ask to allow multiple servers (processes or + * threads) to bind to the same port if they each set the option. + * + * SO_REUSEPORT is what most people would expect SO_REUSEADDR to be, however + * SO_REUSEPORT does not imply SO_REUSEADDR. + * + * This is only available on Linux and kernel 3.9+ + */ +#define LEV_OPT_REUSEABLE_PORT (1u<<7) + +/** + Allocate a new evconnlistener object to listen for incoming TCP connections + on a given file descriptor. + + @param base The event base to associate the listener with. + @param cb A callback to be invoked when a new connection arrives. If the + callback is NULL, the listener will be treated as disabled until the + callback is set. + @param ptr A user-supplied pointer to give to the callback. + @param flags Any number of LEV_OPT_* flags + @param backlog Passed to the listen() call to determine the length of the + acceptable connection backlog. Set to -1 for a reasonable default. + Set to 0 if the socket is already listening. + @param fd The file descriptor to listen on. It must be a nonblocking + file descriptor, and it should already be bound to an appropriate + port and address. +*/ +EVENT2_EXPORT_SYMBOL +struct evconnlistener *evconnlistener_new(struct event_base *base, + evconnlistener_cb cb, void *ptr, unsigned flags, int backlog, + evutil_socket_t fd); +/** + Allocate a new evconnlistener object to listen for incoming TCP connections + on a given address. + + @param base The event base to associate the listener with. + @param cb A callback to be invoked when a new connection arrives. If the + callback is NULL, the listener will be treated as disabled until the + callback is set. + @param ptr A user-supplied pointer to give to the callback. + @param flags Any number of LEV_OPT_* flags + @param backlog Passed to the listen() call to determine the length of the + acceptable connection backlog. Set to -1 for a reasonable default. + @param addr The address to listen for connections on. + @param socklen The length of the address. + */ +EVENT2_EXPORT_SYMBOL +struct evconnlistener *evconnlistener_new_bind(struct event_base *base, + evconnlistener_cb cb, void *ptr, unsigned flags, int backlog, + const struct sockaddr *sa, int socklen); +/** + Disable and deallocate an evconnlistener. + */ +EVENT2_EXPORT_SYMBOL +void evconnlistener_free(struct evconnlistener *lev); +/** + Re-enable an evconnlistener that has been disabled. + */ +EVENT2_EXPORT_SYMBOL +int evconnlistener_enable(struct evconnlistener *lev); +/** + Stop listening for connections on an evconnlistener. + */ +EVENT2_EXPORT_SYMBOL +int evconnlistener_disable(struct evconnlistener *lev); + +/** Return an evconnlistener's associated event_base. */ +EVENT2_EXPORT_SYMBOL +struct event_base *evconnlistener_get_base(struct evconnlistener *lev); + +/** Return the socket that an evconnlistner is listening on. */ +EVENT2_EXPORT_SYMBOL +evutil_socket_t evconnlistener_get_fd(struct evconnlistener *lev); + +/** Change the callback on the listener to cb and its user_data to arg. + */ +EVENT2_EXPORT_SYMBOL +void evconnlistener_set_cb(struct evconnlistener *lev, + evconnlistener_cb cb, void *arg); + +/** Set an evconnlistener's error callback. */ +EVENT2_EXPORT_SYMBOL +void evconnlistener_set_error_cb(struct evconnlistener *lev, + evconnlistener_errorcb errorcb); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/include/event2/rpc.h b/src/include/event2/rpc.h new file mode 100644 index 0000000..dd43df2 --- /dev/null +++ b/src/include/event2/rpc.h @@ -0,0 +1,596 @@ +/* + * Copyright (c) 2006-2007 Niels Provos <[email protected]> + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EVENT2_RPC_H_INCLUDED_ +#define EVENT2_RPC_H_INCLUDED_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @file rpc.h + * + * This header files provides basic support for an RPC server and client. + * + * To support RPCs in a server, every supported RPC command needs to be + * defined and registered. + * + * EVRPC_HEADER(SendCommand, Request, Reply); + * + * SendCommand is the name of the RPC command. + * Request is the name of a structure generated by event_rpcgen.py. + * It contains all parameters relating to the SendCommand RPC. The + * server needs to fill in the Reply structure. + * Reply is the name of a structure generated by event_rpcgen.py. It + * contains the answer to the RPC. + * + * To register an RPC with an HTTP server, you need to first create an RPC + * base with: + * + * struct evrpc_base *base = evrpc_init(http); + * + * A specific RPC can then be registered with + * + * EVRPC_REGISTER(base, SendCommand, Request, Reply, FunctionCB, arg); + * + * when the server receives an appropriately formatted RPC, the user callback + * is invoked. The callback needs to fill in the reply structure. + * + * void FunctionCB(EVRPC_STRUCT(SendCommand)* rpc, void *arg); + * + * To send the reply, call EVRPC_REQUEST_DONE(rpc); + * + * See the regression test for an example. + */ + +/** + Determines if the member has been set in the message + + @param msg the message to inspect + @param member the member variable to test for presences + @return 1 if it's present or 0 otherwise. +*/ +#define EVTAG_HAS(msg, member) \ + ((msg)->member##_set == 1) + +#ifndef EVENT2_RPC_COMPAT_H_INCLUDED_ + +/** + Assigns a value to the member in the message. + + @param msg the message to which to assign a value + @param member the name of the member variable + @param value the value to assign +*/ +#define EVTAG_ASSIGN(msg, member, value) \ + (*(msg)->base->member##_assign)((msg), (value)) +/** + Assigns a value to the member in the message. + + @param msg the message to which to assign a value + @param member the name of the member variable + @param value the value to assign + @param len the length of the value +*/ +#define EVTAG_ASSIGN_WITH_LEN(msg, member, value, len) \ + (*(msg)->base->member##_assign)((msg), (value), (len)) +/** + Returns the value for a member. + + @param msg the message from which to get the value + @param member the name of the member variable + @param pvalue a pointer to the variable to hold the value + @return 0 on success, -1 otherwise. +*/ +#define EVTAG_GET(msg, member, pvalue) \ + (*(msg)->base->member##_get)((msg), (pvalue)) +/** + Returns the value for a member. + + @param msg the message from which to get the value + @param member the name of the member variable + @param pvalue a pointer to the variable to hold the value + @param plen a pointer to the length of the value + @return 0 on success, -1 otherwise. +*/ +#define EVTAG_GET_WITH_LEN(msg, member, pvalue, plen) \ + (*(msg)->base->member##_get)((msg), (pvalue), (plen)) + +#endif /* EVENT2_RPC_COMPAT_H_INCLUDED_ */ + +/** + Adds a value to an array. +*/ +#define EVTAG_ARRAY_ADD_VALUE(msg, member, value) \ + (*(msg)->base->member##_add)((msg), (value)) +/** + Allocates a new entry in the array and returns it. +*/ +#define EVTAG_ARRAY_ADD(msg, member) \ + (*(msg)->base->member##_add)(msg) +/** + Gets a variable at the specified offset from the array. +*/ +#define EVTAG_ARRAY_GET(msg, member, offset, pvalue) \ + (*(msg)->base->member##_get)((msg), (offset), (pvalue)) +/** + Returns the number of entries in the array. +*/ +#define EVTAG_ARRAY_LEN(msg, member) ((msg)->member##_length) + + +struct evbuffer; +struct event_base; +struct evrpc_req_generic; +struct evrpc_request_wrapper; +struct evrpc; + +/** The type of a specific RPC Message + * + * @param rpcname the name of the RPC message + */ +#define EVRPC_STRUCT(rpcname) struct evrpc_req__##rpcname + +struct evhttp_request; +struct evrpc_status; +struct evrpc_hook_meta; + +/** Creates the definitions and prototypes for an RPC + * + * You need to use EVRPC_HEADER to create structures and function prototypes + * needed by the server and client implementation. The structures have to be + * defined in an .rpc file and converted to source code via event_rpcgen.py + * + * @param rpcname the name of the RPC + * @param reqstruct the name of the RPC request structure + * @param replystruct the name of the RPC reply structure + * @see EVRPC_GENERATE() + */ +#define EVRPC_HEADER(rpcname, reqstruct, rplystruct) \ +EVRPC_STRUCT(rpcname) { \ + struct evrpc_hook_meta *hook_meta; \ + struct reqstruct* request; \ + struct rplystruct* reply; \ + struct evrpc* rpc; \ + struct evhttp_request* http_req; \ + struct evbuffer* rpc_data; \ +}; \ +int evrpc_send_request_##rpcname(struct evrpc_pool *, \ + struct reqstruct *, struct rplystruct *, \ + void (*)(struct evrpc_status *, \ + struct reqstruct *, struct rplystruct *, void *cbarg), \ + void *); + +struct evrpc_pool; + +/** use EVRPC_GENERATE instead */ +struct evrpc_request_wrapper *evrpc_make_request_ctx( + struct evrpc_pool *pool, void *request, void *reply, + const char *rpcname, + void (*req_marshal)(struct evbuffer*, void *), + void (*rpl_clear)(void *), + int (*rpl_unmarshal)(void *, struct evbuffer *), + void (*cb)(struct evrpc_status *, void *, void *, void *), + void *cbarg); + +/** Creates a context structure that contains rpc specific information. + * + * EVRPC_MAKE_CTX is used to populate a RPC specific context that + * contains information about marshaling the RPC data types. + * + * @param rpcname the name of the RPC + * @param reqstruct the name of the RPC request structure + * @param replystruct the name of the RPC reply structure + * @param pool the evrpc_pool over which to make the request + * @param request a pointer to the RPC request structure object + * @param reply a pointer to the RPC reply structure object + * @param cb the callback function to call when the RPC has completed + * @param cbarg the argument to supply to the callback + */ +#define EVRPC_MAKE_CTX(rpcname, reqstruct, rplystruct, \ + pool, request, reply, cb, cbarg) \ + evrpc_make_request_ctx(pool, request, reply, \ + #rpcname, \ + (void (*)(struct evbuffer *, void *))reqstruct##_marshal, \ + (void (*)(void *))rplystruct##_clear, \ + (int (*)(void *, struct evbuffer *))rplystruct##_unmarshal, \ + (void (*)(struct evrpc_status *, void *, void *, void *))cb, \ + cbarg) + +/** Generates the code for receiving and sending an RPC message + * + * EVRPC_GENERATE is used to create the code corresponding to sending + * and receiving a particular RPC message + * + * @param rpcname the name of the RPC + * @param reqstruct the name of the RPC request structure + * @param replystruct the name of the RPC reply structure + * @see EVRPC_HEADER() + */ +#define EVRPC_GENERATE(rpcname, reqstruct, rplystruct) \ + int evrpc_send_request_##rpcname(struct evrpc_pool *pool, \ + struct reqstruct *request, struct rplystruct *reply, \ + void (*cb)(struct evrpc_status *, \ + struct reqstruct *, struct rplystruct *, void *cbarg), \ + void *cbarg) { \ + return evrpc_send_request_generic(pool, request, reply, \ + (void (*)(struct evrpc_status *, void *, void *, void *))cb, \ + cbarg, \ + #rpcname, \ + (void (*)(struct evbuffer *, void *))reqstruct##_marshal, \ + (void (*)(void *))rplystruct##_clear, \ + (int (*)(void *, struct evbuffer *))rplystruct##_unmarshal); \ +} + +/** Provides access to the HTTP request object underlying an RPC + * + * Access to the underlying http object; can be used to look at headers or + * for getting the remote ip address + * + * @param rpc_req the rpc request structure provided to the server callback + * @return an struct evhttp_request object that can be inspected for + * HTTP headers or sender information. + */ +#define EVRPC_REQUEST_HTTP(rpc_req) (rpc_req)->http_req + +/** completes the server response to an rpc request */ +void evrpc_request_done(struct evrpc_req_generic *req); + +/** accessors for request and reply */ +void *evrpc_get_request(struct evrpc_req_generic *req); +void *evrpc_get_reply(struct evrpc_req_generic *req); + +/** Creates the reply to an RPC request + * + * EVRPC_REQUEST_DONE is used to answer a request; the reply is expected + * to have been filled in. The request and reply pointers become invalid + * after this call has finished. + * + * @param rpc_req the rpc request structure provided to the server callback + */ +#define EVRPC_REQUEST_DONE(rpc_req) do { \ + struct evrpc_req_generic *req_ = (struct evrpc_req_generic *)(rpc_req); \ + evrpc_request_done(req_); \ +} while (0) + + +struct evrpc_base; +struct evhttp; + +/* functions to start up the rpc system */ + +/** Creates a new rpc base from which RPC requests can be received + * + * @param server a pointer to an existing HTTP server + * @return a newly allocated evrpc_base struct + * @see evrpc_free() + */ +struct evrpc_base *evrpc_init(struct evhttp *server); + +/** + * Frees the evrpc base + * + * For now, you are responsible for making sure that no rpcs are ongoing. + * + * @param base the evrpc_base object to be freed + * @see evrpc_init + */ +void evrpc_free(struct evrpc_base *base); + +/** register RPCs with the HTTP Server + * + * registers a new RPC with the HTTP server, each RPC needs to have + * a unique name under which it can be identified. + * + * @param base the evrpc_base structure in which the RPC should be + * registered. + * @param name the name of the RPC + * @param request the name of the RPC request structure + * @param reply the name of the RPC reply structure + * @param callback the callback that should be invoked when the RPC + * is received. The callback has the following prototype + * void (*callback)(EVRPC_STRUCT(Message)* rpc, void *arg) + * @param cbarg an additional parameter that can be passed to the callback. + * The parameter can be used to carry around state. + */ +#define EVRPC_REGISTER(base, name, request, reply, callback, cbarg) \ + evrpc_register_generic(base, #name, \ + (void (*)(struct evrpc_req_generic *, void *))callback, cbarg, \ + (void *(*)(void *))request##_new, NULL, \ + (void (*)(void *))request##_free, \ + (int (*)(void *, struct evbuffer *))request##_unmarshal, \ + (void *(*)(void *))reply##_new, NULL, \ + (void (*)(void *))reply##_free, \ + (int (*)(void *))reply##_complete, \ + (void (*)(struct evbuffer *, void *))reply##_marshal) + +/** + Low level function for registering an RPC with a server. + + Use EVRPC_REGISTER() instead. + + @see EVRPC_REGISTER() +*/ +int evrpc_register_rpc(struct evrpc_base *, struct evrpc *, + void (*)(struct evrpc_req_generic*, void *), void *); + +/** + * Unregisters an already registered RPC + * + * @param base the evrpc_base object from which to unregister an RPC + * @param name the name of the rpc to unregister + * @return -1 on error or 0 when successful. + * @see EVRPC_REGISTER() + */ +#define EVRPC_UNREGISTER(base, name) evrpc_unregister_rpc((base), #name) + +int evrpc_unregister_rpc(struct evrpc_base *base, const char *name); + +/* + * Client-side RPC support + */ + +struct evhttp_connection; +struct evrpc_status; + +/** launches an RPC and sends it to the server + * + * EVRPC_MAKE_REQUEST() is used by the client to send an RPC to the server. + * + * @param name the name of the RPC + * @param pool the evrpc_pool that contains the connection objects over which + * the request should be sent. + * @param request a pointer to the RPC request structure - it contains the + * data to be sent to the server. + * @param reply a pointer to the RPC reply structure. It is going to be filled + * if the request was answered successfully + * @param cb the callback to invoke when the RPC request has been answered + * @param cbarg an additional argument to be passed to the client + * @return 0 on success, -1 on failure + */ +#define EVRPC_MAKE_REQUEST(name, pool, request, reply, cb, cbarg) \ + evrpc_send_request_##name((pool), (request), (reply), (cb), (cbarg)) + +/** + Makes an RPC request based on the provided context. + + This is a low-level function and should not be used directly + unless a custom context object is provided. Use EVRPC_MAKE_REQUEST() + instead. + + @param ctx a context from EVRPC_MAKE_CTX() + @returns 0 on success, -1 otherwise. + @see EVRPC_MAKE_REQUEST(), EVRPC_MAKE_CTX() +*/ +int evrpc_make_request(struct evrpc_request_wrapper *ctx); + +/** creates an rpc connection pool + * + * a pool has a number of connections associated with it. + * rpc requests are always made via a pool. + * + * @param base a pointer to an struct event_based object; can be left NULL + * in singled-threaded applications + * @return a newly allocated struct evrpc_pool object + * @see evrpc_pool_free() + */ +struct evrpc_pool *evrpc_pool_new(struct event_base *base); +/** frees an rpc connection pool + * + * @param pool a pointer to an evrpc_pool allocated via evrpc_pool_new() + * @see evrpc_pool_new() + */ +void evrpc_pool_free(struct evrpc_pool *pool); + +/** + * Adds a connection over which rpc can be dispatched to the pool. + * + * The connection object must have been newly created. + * + * @param pool the pool to which to add the connection + * @param evcon the connection to add to the pool. + */ +void evrpc_pool_add_connection(struct evrpc_pool *pool, + struct evhttp_connection *evcon); + +/** + * Removes a connection from the pool. + * + * The connection object must have been newly created. + * + * @param pool the pool from which to remove the connection + * @param evcon the connection to remove from the pool. + */ +void evrpc_pool_remove_connection(struct evrpc_pool *pool, + struct evhttp_connection *evcon); + +/** + * Sets the timeout in secs after which a request has to complete. The + * RPC is completely aborted if it does not complete by then. Setting + * the timeout to 0 means that it never timeouts and can be used to + * implement callback type RPCs. + * + * Any connection already in the pool will be updated with the new + * timeout. Connections added to the pool after set_timeout has be + * called receive the pool timeout only if no timeout has been set + * for the connection itself. + * + * @param pool a pointer to a struct evrpc_pool object + * @param timeout_in_secs the number of seconds after which a request should + * timeout and a failure be returned to the callback. + */ +void evrpc_pool_set_timeout(struct evrpc_pool *pool, int timeout_in_secs); + +/** + * Hooks for changing the input and output of RPCs; this can be used to + * implement compression, authentication, encryption, ... + */ + +enum EVRPC_HOOK_TYPE { + EVRPC_INPUT, /**< apply the function to an input hook */ + EVRPC_OUTPUT /**< apply the function to an output hook */ +}; + +#ifndef _WIN32 +/** Deprecated alias for EVRPC_INPUT. Not available on windows, where it + * conflicts with platform headers. */ +#define INPUT EVRPC_INPUT +/** Deprecated alias for EVRPC_OUTPUT. Not available on windows, where it + * conflicts with platform headers. */ +#define OUTPUT EVRPC_OUTPUT +#endif + +/** + * Return value from hook processing functions + */ + +enum EVRPC_HOOK_RESULT { + EVRPC_TERMINATE = -1, /**< indicates the rpc should be terminated */ + EVRPC_CONTINUE = 0, /**< continue processing the rpc */ + EVRPC_PAUSE = 1 /**< pause processing request until resumed */ +}; + +/** adds a processing hook to either an rpc base or rpc pool + * + * If a hook returns TERMINATE, the processing is aborted. On CONTINUE, + * the request is immediately processed after the hook returns. If the + * hook returns PAUSE, request processing stops until evrpc_resume_request() + * has been called. + * + * The add functions return handles that can be used for removing hooks. + * + * @param vbase a pointer to either struct evrpc_base or struct evrpc_pool + * @param hook_type either INPUT or OUTPUT + * @param cb the callback to call when the hook is activated + * @param cb_arg an additional argument for the callback + * @return a handle to the hook so it can be removed later + * @see evrpc_remove_hook() + */ +void *evrpc_add_hook(void *vbase, + enum EVRPC_HOOK_TYPE hook_type, + int (*cb)(void *, struct evhttp_request *, struct evbuffer *, void *), + void *cb_arg); + +/** removes a previously added hook + * + * @param vbase a pointer to either struct evrpc_base or struct evrpc_pool + * @param hook_type either INPUT or OUTPUT + * @param handle a handle returned by evrpc_add_hook() + * @return 1 on success or 0 on failure + * @see evrpc_add_hook() + */ +int evrpc_remove_hook(void *vbase, + enum EVRPC_HOOK_TYPE hook_type, + void *handle); + +/** resume a paused request + * + * @param vbase a pointer to either struct evrpc_base or struct evrpc_pool + * @param ctx the context pointer provided to the original hook call + */ +int +evrpc_resume_request(void *vbase, void *ctx, enum EVRPC_HOOK_RESULT res); + +/** adds meta data to request + * + * evrpc_hook_add_meta() allows hooks to add meta data to a request. for + * a client request, the meta data can be inserted by an outgoing request hook + * and retrieved by the incoming request hook. + * + * @param ctx the context provided to the hook call + * @param key a NUL-terminated c-string + * @param data the data to be associated with the key + * @param data_size the size of the data + */ +void evrpc_hook_add_meta(void *ctx, const char *key, + const void *data, size_t data_size); + +/** retrieves meta data previously associated + * + * evrpc_hook_find_meta() can be used to retrieve meta data associated to a + * request by a previous hook. + * @param ctx the context provided to the hook call + * @param key a NUL-terminated c-string + * @param data pointer to a data pointer that will contain the retrieved data + * @param data_size pointer to the size of the data + * @return 0 on success or -1 on failure + */ +int evrpc_hook_find_meta(void *ctx, const char *key, + void **data, size_t *data_size); + +/** + * returns the connection object associated with the request + * + * @param ctx the context provided to the hook call + * @return a pointer to the evhttp_connection object + */ +struct evhttp_connection *evrpc_hook_get_connection(void *ctx); + +/** + Function for sending a generic RPC request. + + Do not call this function directly, use EVRPC_MAKE_REQUEST() instead. + + @see EVRPC_MAKE_REQUEST() + */ +int evrpc_send_request_generic(struct evrpc_pool *pool, + void *request, void *reply, + void (*cb)(struct evrpc_status *, void *, void *, void *), + void *cb_arg, + const char *rpcname, + void (*req_marshal)(struct evbuffer *, void *), + void (*rpl_clear)(void *), + int (*rpl_unmarshal)(void *, struct evbuffer *)); + +/** + Function for registering a generic RPC with the RPC base. + + Do not call this function directly, use EVRPC_REGISTER() instead. + + @see EVRPC_REGISTER() + */ +int +evrpc_register_generic(struct evrpc_base *base, const char *name, + void (*callback)(struct evrpc_req_generic *, void *), void *cbarg, + void *(*req_new)(void *), void *req_new_arg, void (*req_free)(void *), + int (*req_unmarshal)(void *, struct evbuffer *), + void *(*rpl_new)(void *), void *rpl_new_arg, void (*rpl_free)(void *), + int (*rpl_complete)(void *), + void (*rpl_marshal)(struct evbuffer *, void *)); + +/** accessors for obscure and undocumented functionality */ +struct evrpc_pool* evrpc_request_get_pool(struct evrpc_request_wrapper *ctx); +void evrpc_request_set_pool(struct evrpc_request_wrapper *ctx, + struct evrpc_pool *pool); +void evrpc_request_set_cb(struct evrpc_request_wrapper *ctx, + void (*cb)(struct evrpc_status*, void *request, void *reply, void *arg), + void *cb_arg); + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_RPC_H_INCLUDED_ */ diff --git a/src/include/event2/rpc_compat.h b/src/include/event2/rpc_compat.h new file mode 100644 index 0000000..8d8334d --- /dev/null +++ b/src/include/event2/rpc_compat.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2006-2007 Niels Provos <[email protected]> + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EVENT2_RPC_COMPAT_H_INCLUDED_ +#define EVENT2_RPC_COMPAT_H_INCLUDED_ + +/** @file event2/rpc_compat.h + + Deprecated versions of the functions in rpc.h: provided only for + backwards compatibility. + + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** backwards compatible accessors that work only with gcc */ +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) + +#undef EVTAG_ASSIGN +#undef EVTAG_GET +#undef EVTAG_ADD + +#define EVTAG_ASSIGN(msg, member, args...) \ + (*(msg)->base->member##_assign)(msg, ## args) +#define EVTAG_GET(msg, member, args...) \ + (*(msg)->base->member##_get)(msg, ## args) +#define EVTAG_ADD(msg, member, args...) \ + (*(msg)->base->member##_add)(msg, ## args) +#endif +#define EVTAG_LEN(msg, member) ((msg)->member##_length) + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_EVENT_COMPAT_H_INCLUDED_ */ diff --git a/src/include/event2/rpc_struct.h b/src/include/event2/rpc_struct.h new file mode 100644 index 0000000..8f691f4 --- /dev/null +++ b/src/include/event2/rpc_struct.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2006-2007 Niels Provos <[email protected]> + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EVENT2_RPC_STRUCT_H_INCLUDED_ +#define EVENT2_RPC_STRUCT_H_INCLUDED_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @file event2/rpc_struct.h + + Structures used by rpc.h. Using these structures directly may harm + forward compatibility: be careful! + + */ + +/** + * provides information about the completed RPC request. + */ +struct evrpc_status { +#define EVRPC_STATUS_ERR_NONE 0 +#define EVRPC_STATUS_ERR_TIMEOUT 1 +#define EVRPC_STATUS_ERR_BADPAYLOAD 2 +#define EVRPC_STATUS_ERR_UNSTARTED 3 +#define EVRPC_STATUS_ERR_HOOKABORTED 4 + int error; + + /* for looking at headers or other information */ + struct evhttp_request *http_req; +}; + +/* the structure below needs to be synchronized with evrpc_req_generic */ + +/* Encapsulates a request */ +struct evrpc { + TAILQ_ENTRY(evrpc) next; + + /* the URI at which the request handler lives */ + const char* uri; + + /* creates a new request structure */ + void *(*request_new)(void *); + void *request_new_arg; + + /* frees the request structure */ + void (*request_free)(void *); + + /* unmarshals the buffer into the proper request structure */ + int (*request_unmarshal)(void *, struct evbuffer *); + + /* creates a new reply structure */ + void *(*reply_new)(void *); + void *reply_new_arg; + + /* frees the reply structure */ + void (*reply_free)(void *); + + /* verifies that the reply is valid */ + int (*reply_complete)(void *); + + /* marshals the reply into a buffer */ + void (*reply_marshal)(struct evbuffer*, void *); + + /* the callback invoked for each received rpc */ + void (*cb)(struct evrpc_req_generic *, void *); + void *cb_arg; + + /* reference for further configuration */ + struct evrpc_base *base; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_RPC_STRUCT_H_INCLUDED_ */ diff --git a/src/include/event2/tag.h b/src/include/event2/tag.h new file mode 100644 index 0000000..2f73bfc --- /dev/null +++ b/src/include/event2/tag.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2000-2007 Niels Provos <[email protected]> + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EVENT2_TAG_H_INCLUDED_ +#define EVENT2_TAG_H_INCLUDED_ + +/** @file event2/tag.h + + Helper functions for reading and writing tagged data onto buffers. + + */ + +#include <event2/visibility.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#include <event2/event-config.h> +#ifdef EVENT__HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef EVENT__HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + +/* For int types. */ +#include <event2/util.h> + +struct evbuffer; + +/* + * Marshaling tagged data - We assume that all tags are inserted in their + * numeric order - so that unknown tags will always be higher than the + * known ones - and we can just ignore the end of an event buffer. + */ + +EVENT2_EXPORT_SYMBOL +void evtag_init(void); + +/** + Unmarshals the header and returns the length of the payload + + @param evbuf the buffer from which to unmarshal data + @param ptag a pointer in which the tag id is being stored + @returns -1 on failure or the number of bytes in the remaining payload. +*/ +EVENT2_EXPORT_SYMBOL +int evtag_unmarshal_header(struct evbuffer *evbuf, ev_uint32_t *ptag); + +EVENT2_EXPORT_SYMBOL +void evtag_marshal(struct evbuffer *evbuf, ev_uint32_t tag, const void *data, + ev_uint32_t len); +EVENT2_EXPORT_SYMBOL +void evtag_marshal_buffer(struct evbuffer *evbuf, ev_uint32_t tag, + struct evbuffer *data); + +/** + Encode an integer and store it in an evbuffer. + + We encode integers by nybbles; the first nibble contains the number + of significant nibbles - 1; this allows us to encode up to 64-bit + integers. This function is byte-order independent. + + @param evbuf evbuffer to store the encoded number + @param number a 32-bit integer + */ +EVENT2_EXPORT_SYMBOL +void evtag_encode_int(struct evbuffer *evbuf, ev_uint32_t number); +EVENT2_EXPORT_SYMBOL +void evtag_encode_int64(struct evbuffer *evbuf, ev_uint64_t number); + +EVENT2_EXPORT_SYMBOL +void evtag_marshal_int(struct evbuffer *evbuf, ev_uint32_t tag, + ev_uint32_t integer); +EVENT2_EXPORT_SYMBOL +void evtag_marshal_int64(struct evbuffer *evbuf, ev_uint32_t tag, + ev_uint64_t integer); + +EVENT2_EXPORT_SYMBOL +void evtag_marshal_string(struct evbuffer *buf, ev_uint32_t tag, + const char *string); + +EVENT2_EXPORT_SYMBOL +void evtag_marshal_timeval(struct evbuffer *evbuf, ev_uint32_t tag, + struct timeval *tv); + +EVENT2_EXPORT_SYMBOL +int evtag_unmarshal(struct evbuffer *src, ev_uint32_t *ptag, + struct evbuffer *dst); +EVENT2_EXPORT_SYMBOL +int evtag_peek(struct evbuffer *evbuf, ev_uint32_t *ptag); +EVENT2_EXPORT_SYMBOL +int evtag_peek_length(struct evbuffer *evbuf, ev_uint32_t *plength); +EVENT2_EXPORT_SYMBOL +int evtag_payload_length(struct evbuffer *evbuf, ev_uint32_t *plength); +EVENT2_EXPORT_SYMBOL +int evtag_consume(struct evbuffer *evbuf); + +EVENT2_EXPORT_SYMBOL +int evtag_unmarshal_int(struct evbuffer *evbuf, ev_uint32_t need_tag, + ev_uint32_t *pinteger); +EVENT2_EXPORT_SYMBOL +int evtag_unmarshal_int64(struct evbuffer *evbuf, ev_uint32_t need_tag, + ev_uint64_t *pinteger); + +EVENT2_EXPORT_SYMBOL +int evtag_unmarshal_fixed(struct evbuffer *src, ev_uint32_t need_tag, + void *data, size_t len); + +EVENT2_EXPORT_SYMBOL +int evtag_unmarshal_string(struct evbuffer *evbuf, ev_uint32_t need_tag, + char **pstring); + +EVENT2_EXPORT_SYMBOL +int evtag_unmarshal_timeval(struct evbuffer *evbuf, ev_uint32_t need_tag, + struct timeval *ptv); + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_TAG_H_INCLUDED_ */ diff --git a/src/include/event2/tag_compat.h b/src/include/event2/tag_compat.h new file mode 100644 index 0000000..a276c0d --- /dev/null +++ b/src/include/event2/tag_compat.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2000-2007 Niels Provos <[email protected]> + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EVENT2_TAG_COMPAT_H_INCLUDED_ +#define EVENT2_TAG_COMPAT_H_INCLUDED_ + +/** @file event2/tag_compat.h + + Obsolete/deprecated functions from tag.h; provided only for backwards + compatibility. + */ + +/** + @name Misnamed functions + + @deprecated These macros are deprecated because their names don't follow + Libevent's naming conventions. Use evtag_encode_int and + evtag_encode_int64 instead. + + @{ +*/ +#define encode_int(evbuf, number) evtag_encode_int((evbuf), (number)) +#define encode_int64(evbuf, number) evtag_encode_int64((evbuf), (number)) +/**@}*/ + +#endif /* EVENT2_TAG_H_INCLUDED_ */ diff --git a/src/include/event2/thread.h b/src/include/event2/thread.h new file mode 100644 index 0000000..b519986 --- /dev/null +++ b/src/include/event2/thread.h @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2008-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EVENT2_THREAD_H_INCLUDED_ +#define EVENT2_THREAD_H_INCLUDED_ + +/** @file event2/thread.h + + Functions for multi-threaded applications using Libevent. + + When using a multi-threaded application in which multiple threads + add and delete events from a single event base, Libevent needs to + lock its data structures. + + Like the memory-management function hooks, all of the threading functions + _must_ be set up before an event_base is created if you want the base to + use them. + + Most programs will either be using Windows threads or Posix threads. You + can configure Libevent to use one of these event_use_windows_threads() or + event_use_pthreads() respectively. If you're using another threading + library, you'll need to configure threading functions manually using + evthread_set_lock_callbacks() and evthread_set_condition_callbacks(). + + */ + +#include <event2/visibility.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#include <event2/event-config.h> + +/** + @name Flags passed to lock functions + + @{ +*/ +/** A flag passed to a locking callback when the lock was allocated as a + * read-write lock, and we want to acquire or release the lock for writing. */ +#define EVTHREAD_WRITE 0x04 +/** A flag passed to a locking callback when the lock was allocated as a + * read-write lock, and we want to acquire or release the lock for reading. */ +#define EVTHREAD_READ 0x08 +/** A flag passed to a locking callback when we don't want to block waiting + * for the lock; if we can't get the lock immediately, we will instead + * return nonzero from the locking callback. */ +#define EVTHREAD_TRY 0x10 +/**@}*/ + +#if !defined(EVENT__DISABLE_THREAD_SUPPORT) || defined(EVENT_IN_DOXYGEN_) + +#define EVTHREAD_LOCK_API_VERSION 1 + +/** + @name Types of locks + + @{*/ +/** A recursive lock is one that can be acquired multiple times at once by the + * same thread. No other process can allocate the lock until the thread that + * has been holding it has unlocked it as many times as it locked it. */ +#define EVTHREAD_LOCKTYPE_RECURSIVE 1 +/* A read-write lock is one that allows multiple simultaneous readers, but + * where any one writer excludes all other writers and readers. */ +#define EVTHREAD_LOCKTYPE_READWRITE 2 +/**@}*/ + +/** This structure describes the interface a threading library uses for + * locking. It's used to tell evthread_set_lock_callbacks() how to use + * locking on this platform. + */ +struct evthread_lock_callbacks { + /** The current version of the locking API. Set this to + * EVTHREAD_LOCK_API_VERSION */ + int lock_api_version; + /** Which kinds of locks does this version of the locking API + * support? A bitfield of EVTHREAD_LOCKTYPE_RECURSIVE and + * EVTHREAD_LOCKTYPE_READWRITE. + * + * (Note that RECURSIVE locks are currently mandatory, and + * READWRITE locks are not currently used.) + **/ + unsigned supported_locktypes; + /** Function to allocate and initialize new lock of type 'locktype'. + * Returns NULL on failure. */ + void *(*alloc)(unsigned locktype); + /** Funtion to release all storage held in 'lock', which was created + * with type 'locktype'. */ + void (*free)(void *lock, unsigned locktype); + /** Acquire an already-allocated lock at 'lock' with mode 'mode'. + * Returns 0 on success, and nonzero on failure. */ + int (*lock)(unsigned mode, void *lock); + /** Release a lock at 'lock' using mode 'mode'. Returns 0 on success, + * and nonzero on failure. */ + int (*unlock)(unsigned mode, void *lock); +}; + +/** Sets a group of functions that Libevent should use for locking. + * For full information on the required callback API, see the + * documentation for the individual members of evthread_lock_callbacks. + * + * Note that if you're using Windows or the Pthreads threading library, you + * probably shouldn't call this function; instead, use + * evthread_use_windows_threads() or evthread_use_posix_threads() if you can. + */ +EVENT2_EXPORT_SYMBOL +int evthread_set_lock_callbacks(const struct evthread_lock_callbacks *); + +#define EVTHREAD_CONDITION_API_VERSION 1 + +struct timeval; + +/** This structure describes the interface a threading library uses for + * condition variables. It's used to tell evthread_set_condition_callbacks + * how to use locking on this platform. + */ +struct evthread_condition_callbacks { + /** The current version of the conditions API. Set this to + * EVTHREAD_CONDITION_API_VERSION */ + int condition_api_version; + /** Function to allocate and initialize a new condition variable. + * Returns the condition variable on success, and NULL on failure. + * The 'condtype' argument will be 0 with this API version. + */ + void *(*alloc_condition)(unsigned condtype); + /** Function to free a condition variable. */ + void (*free_condition)(void *cond); + /** Function to signal a condition variable. If 'broadcast' is 1, all + * threads waiting on 'cond' should be woken; otherwise, only on one + * thread is worken. Should return 0 on success, -1 on failure. + * This function will only be called while holding the associated + * lock for the condition. + */ + int (*signal_condition)(void *cond, int broadcast); + /** Function to wait for a condition variable. The lock 'lock' + * will be held when this function is called; should be released + * while waiting for the condition to be come signalled, and + * should be held again when this function returns. + * If timeout is provided, it is interval of seconds to wait for + * the event to become signalled; if it is NULL, the function + * should wait indefinitely. + * + * The function should return -1 on error; 0 if the condition + * was signalled, or 1 on a timeout. */ + int (*wait_condition)(void *cond, void *lock, + const struct timeval *timeout); +}; + +/** Sets a group of functions that Libevent should use for condition variables. + * For full information on the required callback API, see the + * documentation for the individual members of evthread_condition_callbacks. + * + * Note that if you're using Windows or the Pthreads threading library, you + * probably shouldn't call this function; instead, use + * evthread_use_windows_threads() or evthread_use_pthreads() if you can. + */ +EVENT2_EXPORT_SYMBOL +int evthread_set_condition_callbacks( + const struct evthread_condition_callbacks *); + +/** + Sets the function for determining the thread id. + + @param base the event base for which to set the id function + @param id_fn the identify function Libevent should invoke to + determine the identity of a thread. +*/ +EVENT2_EXPORT_SYMBOL +void evthread_set_id_callback( + unsigned long (*id_fn)(void)); + +#if (defined(_WIN32) && !defined(EVENT__DISABLE_THREAD_SUPPORT)) || defined(EVENT_IN_DOXYGEN_) +/** Sets up Libevent for use with Windows builtin locking and thread ID + functions. Unavailable if Libevent is not built for Windows. + + @return 0 on success, -1 on failure. */ +EVENT2_EXPORT_SYMBOL +int evthread_use_windows_threads(void); +/** + Defined if Libevent was built with support for evthread_use_windows_threads() +*/ +#define EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED 1 +#endif + +#if defined(EVENT__HAVE_PTHREADS) || defined(EVENT_IN_DOXYGEN_) +/** Sets up Libevent for use with Pthreads locking and thread ID functions. + Unavailable if Libevent is not build for use with pthreads. Requires + libraries to link against Libevent_pthreads as well as Libevent. + + @return 0 on success, -1 on failure. */ +EVENT2_EXPORT_SYMBOL +int evthread_use_pthreads(void); +/** Defined if Libevent was built with support for evthread_use_pthreads() */ +#define EVTHREAD_USE_PTHREADS_IMPLEMENTED 1 + +#endif + +/** Enable debugging wrappers around the current lock callbacks. If Libevent + * makes one of several common locking errors, exit with an assertion failure. + * + * If you're going to call this function, you must do so before any locks are + * allocated. + **/ +EVENT2_EXPORT_SYMBOL +void evthread_enable_lock_debugging(void); + +/* Old (misspelled) version: This is deprecated; use + * evthread_enable_log_debugging instead. */ +EVENT2_EXPORT_SYMBOL +void evthread_enable_lock_debuging(void); + +#endif /* EVENT__DISABLE_THREAD_SUPPORT */ + +struct event_base; +/** Make sure it's safe to tell an event base to wake up from another thread + or a signal handler. + + You shouldn't need to call this by hand; configuring the base with thread + support should be necessary and sufficient. + + @return 0 on success, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int evthread_make_base_notifiable(struct event_base *base); + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_THREAD_H_INCLUDED_ */ diff --git a/src/include/event2/util.h b/src/include/event2/util.h new file mode 100644 index 0000000..dd4bbb6 --- /dev/null +++ b/src/include/event2/util.h @@ -0,0 +1,866 @@ +/* + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EVENT2_UTIL_H_INCLUDED_ +#define EVENT2_UTIL_H_INCLUDED_ + +/** @file event2/util.h + + Common convenience functions for cross-platform portability and + related socket manipulations. + + */ +#include <event2/visibility.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#include <event2/event-config.h> +#ifdef EVENT__HAVE_SYS_TIME_H +#include <sys/time.h> +#endif +#ifdef EVENT__HAVE_STDINT_H +#include <stdint.h> +#elif defined(EVENT__HAVE_INTTYPES_H) +#include <inttypes.h> +#endif +#ifdef EVENT__HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef EVENT__HAVE_STDDEF_H +#include <stddef.h> +#endif +#ifdef _MSC_VER +#include <BaseTsd.h> +#endif +#include <stdarg.h> +#ifdef EVENT__HAVE_NETDB_H +#if !defined(_GNU_SOURCE) +#define _GNU_SOURCE +#endif +#include <netdb.h> +#endif + +#ifdef _WIN32 +#include <winsock2.h> +#ifdef EVENT__HAVE_GETADDRINFO +/* for EAI_* definitions. */ +#include <ws2tcpip.h> +#endif +#else +#ifdef EVENT__HAVE_ERRNO_H +#include <errno.h> +#endif +#include <sys/socket.h> +#endif + +#include <time.h> + +/* Some openbsd autoconf versions get the name of this macro wrong. */ +#if defined(EVENT__SIZEOF_VOID__) && !defined(EVENT__SIZEOF_VOID_P) +#define EVENT__SIZEOF_VOID_P EVENT__SIZEOF_VOID__ +#endif + +/** + * @name Standard integer types. + * + * Integer type definitions for types that are supposed to be defined in the + * C99-specified stdint.h. Shamefully, some platforms do not include + * stdint.h, so we need to replace it. (If you are on a platform like this, + * your C headers are now over 10 years out of date. You should bug them to + * do something about this.) + * + * We define: + * + * <dl> + * <dt>ev_uint64_t, ev_uint32_t, ev_uint16_t, ev_uint8_t</dt> + * <dd>unsigned integer types of exactly 64, 32, 16, and 8 bits + * respectively.</dd> + * <dt>ev_int64_t, ev_int32_t, ev_int16_t, ev_int8_t</dt> + * <dd>signed integer types of exactly 64, 32, 16, and 8 bits + * respectively.</dd> + * <dt>ev_uintptr_t, ev_intptr_t</dt> + * <dd>unsigned/signed integers large enough + * to hold a pointer without loss of bits.</dd> + * <dt>ev_ssize_t</dt> + * <dd>A signed type of the same size as size_t</dd> + * <dt>ev_off_t</dt> + * <dd>A signed type typically used to represent offsets within a + * (potentially large) file</dd> + * + * @{ + */ +#ifdef EVENT__HAVE_UINT64_T +#define ev_uint64_t uint64_t +#define ev_int64_t int64_t +#elif defined(_WIN32) +#define ev_uint64_t unsigned __int64 +#define ev_int64_t signed __int64 +#elif EVENT__SIZEOF_LONG_LONG == 8 +#define ev_uint64_t unsigned long long +#define ev_int64_t long long +#elif EVENT__SIZEOF_LONG == 8 +#define ev_uint64_t unsigned long +#define ev_int64_t long +#elif defined(EVENT_IN_DOXYGEN_) +#define ev_uint64_t ... +#define ev_int64_t ... +#else +#error "No way to define ev_uint64_t" +#endif + +#ifdef EVENT__HAVE_UINT32_T +#define ev_uint32_t uint32_t +#define ev_int32_t int32_t +#elif defined(_WIN32) +#define ev_uint32_t unsigned int +#define ev_int32_t signed int +#elif EVENT__SIZEOF_LONG == 4 +#define ev_uint32_t unsigned long +#define ev_int32_t signed long +#elif EVENT__SIZEOF_INT == 4 +#define ev_uint32_t unsigned int +#define ev_int32_t signed int +#elif defined(EVENT_IN_DOXYGEN_) +#define ev_uint32_t ... +#define ev_int32_t ... +#else +#error "No way to define ev_uint32_t" +#endif + +#ifdef EVENT__HAVE_UINT16_T +#define ev_uint16_t uint16_t +#define ev_int16_t int16_t +#elif defined(_WIN32) +#define ev_uint16_t unsigned short +#define ev_int16_t signed short +#elif EVENT__SIZEOF_INT == 2 +#define ev_uint16_t unsigned int +#define ev_int16_t signed int +#elif EVENT__SIZEOF_SHORT == 2 +#define ev_uint16_t unsigned short +#define ev_int16_t signed short +#elif defined(EVENT_IN_DOXYGEN_) +#define ev_uint16_t ... +#define ev_int16_t ... +#else +#error "No way to define ev_uint16_t" +#endif + +#ifdef EVENT__HAVE_UINT8_T +#define ev_uint8_t uint8_t +#define ev_int8_t int8_t +#elif defined(EVENT_IN_DOXYGEN_) +#define ev_uint8_t ... +#define ev_int8_t ... +#else +#define ev_uint8_t unsigned char +#define ev_int8_t signed char +#endif + +#ifdef EVENT__HAVE_UINTPTR_T +#define ev_uintptr_t uintptr_t +#define ev_intptr_t intptr_t +#elif EVENT__SIZEOF_VOID_P <= 4 +#define ev_uintptr_t ev_uint32_t +#define ev_intptr_t ev_int32_t +#elif EVENT__SIZEOF_VOID_P <= 8 +#define ev_uintptr_t ev_uint64_t +#define ev_intptr_t ev_int64_t +#elif defined(EVENT_IN_DOXYGEN_) +#define ev_uintptr_t ... +#define ev_intptr_t ... +#else +#error "No way to define ev_uintptr_t" +#endif + +#ifdef EVENT__ssize_t +#define ev_ssize_t EVENT__ssize_t +#else +#define ev_ssize_t ssize_t +#endif + +/* Note that we define ev_off_t based on the compile-time size of off_t that + * we used to build Libevent, and not based on the current size of off_t. + * (For example, we don't define ev_off_t to off_t.). We do this because + * some systems let you build your software with different off_t sizes + * at runtime, and so putting in any dependency on off_t would risk API + * mismatch. + */ +#ifdef _WIN32 +#define ev_off_t ev_int64_t +#elif EVENT__SIZEOF_OFF_T == 8 +#define ev_off_t ev_int64_t +#elif EVENT__SIZEOF_OFF_T == 4 +#define ev_off_t ev_int32_t +#elif defined(EVENT_IN_DOXYGEN_) +#define ev_off_t ... +#else +#define ev_off_t off_t +#endif +/**@}*/ + +/* Limits for integer types. + + We're making two assumptions here: + - The compiler does constant folding properly. + - The platform does signed arithmetic in two's complement. +*/ + +/** + @name Limits for integer types + + These macros hold the largest or smallest values possible for the + ev_[u]int*_t types. + + @{ +*/ +#ifndef EVENT__HAVE_STDINT_H +#define EV_UINT64_MAX ((((ev_uint64_t)0xffffffffUL) << 32) | 0xffffffffUL) +#define EV_INT64_MAX ((((ev_int64_t) 0x7fffffffL) << 32) | 0xffffffffL) +#define EV_INT64_MIN ((-EV_INT64_MAX) - 1) +#define EV_UINT32_MAX ((ev_uint32_t)0xffffffffUL) +#define EV_INT32_MAX ((ev_int32_t) 0x7fffffffL) +#define EV_INT32_MIN ((-EV_INT32_MAX) - 1) +#define EV_UINT16_MAX ((ev_uint16_t)0xffffUL) +#define EV_INT16_MAX ((ev_int16_t) 0x7fffL) +#define EV_INT16_MIN ((-EV_INT16_MAX) - 1) +#define EV_UINT8_MAX 255 +#define EV_INT8_MAX 127 +#define EV_INT8_MIN ((-EV_INT8_MAX) - 1) +#else +#define EV_UINT64_MAX UINT64_MAX +#define EV_INT64_MAX INT64_MAX +#define EV_INT64_MIN INT64_MIN +#define EV_UINT32_MAX UINT32_MAX +#define EV_INT32_MAX INT32_MAX +#define EV_INT32_MIN INT32_MIN +#define EV_UINT16_MAX UINT16_MAX +#define EV_INT16_MAX INT16_MAX +#define EV_UINT8_MAX UINT8_MAX +#define EV_INT8_MAX INT8_MAX +#define EV_INT8_MIN INT8_MIN +/** @} */ +#endif + + +/** + @name Limits for SIZE_T and SSIZE_T + + @{ +*/ +#if EVENT__SIZEOF_SIZE_T == 8 +#define EV_SIZE_MAX EV_UINT64_MAX +#define EV_SSIZE_MAX EV_INT64_MAX +#elif EVENT__SIZEOF_SIZE_T == 4 +#define EV_SIZE_MAX EV_UINT32_MAX +#define EV_SSIZE_MAX EV_INT32_MAX +#elif defined(EVENT_IN_DOXYGEN_) +#define EV_SIZE_MAX ... +#define EV_SSIZE_MAX ... +#else +#error "No way to define SIZE_MAX" +#endif + +#define EV_SSIZE_MIN ((-EV_SSIZE_MAX) - 1) +/**@}*/ + +#ifdef _WIN32 +#define ev_socklen_t int +#elif defined(EVENT__socklen_t) +#define ev_socklen_t EVENT__socklen_t +#else +#define ev_socklen_t socklen_t +#endif + +#ifdef EVENT__HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY +#if !defined(EVENT__HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY) \ + && !defined(ss_family) +#define ss_family __ss_family +#endif +#endif + +/** + * A type wide enough to hold the output of "socket()" or "accept()". On + * Windows, this is an intptr_t; elsewhere, it is an int. */ +#ifdef _WIN32 +#define evutil_socket_t intptr_t +#else +#define evutil_socket_t int +#endif + +/** + * Structure to hold information about a monotonic timer + * + * Use this with evutil_configure_monotonic_time() and + * evutil_gettime_monotonic(). + * + * This is an opaque structure; you can allocate one using + * evutil_monotonic_timer_new(). + * + * @see evutil_monotonic_timer_new(), evutil_monotonic_timer_free(), + * evutil_configure_monotonic_time(), evutil_gettime_monotonic() + */ +struct evutil_monotonic_timer +#ifdef EVENT_IN_DOXYGEN_ +{/*Empty body so that doxygen will generate documentation here.*/} +#endif +; + +#define EV_MONOT_PRECISE 1 +#define EV_MONOT_FALLBACK 2 + +/** Format a date string using RFC 1123 format (used in HTTP). + * If `tm` is NULL, current system's time will be used. + * The number of characters written will be returned. + * One should check if the return value is smaller than `datelen` to check if + * the result is truncated or not. + */ +EVENT2_EXPORT_SYMBOL int +evutil_date_rfc1123(char *date, const size_t datelen, const struct tm *tm); + +/** Allocate a new struct evutil_monotonic_timer for use with the + * evutil_configure_monotonic_time() and evutil_gettime_monotonic() + * functions. You must configure the timer with + * evutil_configure_monotonic_time() before using it. + */ +EVENT2_EXPORT_SYMBOL +struct evutil_monotonic_timer * evutil_monotonic_timer_new(void); + +/** Free a struct evutil_monotonic_timer that was allocated using + * evutil_monotonic_timer_new(). + */ +EVENT2_EXPORT_SYMBOL +void evutil_monotonic_timer_free(struct evutil_monotonic_timer *timer); + +/** Set up a struct evutil_monotonic_timer; flags can include + * EV_MONOT_PRECISE and EV_MONOT_FALLBACK. + */ +EVENT2_EXPORT_SYMBOL +int evutil_configure_monotonic_time(struct evutil_monotonic_timer *timer, + int flags); + +/** Query the current monotonic time from a struct evutil_monotonic_timer + * previously configured with evutil_configure_monotonic_time(). Monotonic + * time is guaranteed never to run in reverse, but is not necessarily epoch- + * based, or relative to any other definite point. Use it to make reliable + * measurements of elapsed time between events even when the system time + * may be changed. + * + * It is not safe to use this funtion on the same timer from multiple + * threads. + */ +EVENT2_EXPORT_SYMBOL +int evutil_gettime_monotonic(struct evutil_monotonic_timer *timer, + struct timeval *tp); + +/** Create two new sockets that are connected to each other. + + On Unix, this simply calls socketpair(). On Windows, it uses the + loopback network interface on 127.0.0.1, and only + AF_INET,SOCK_STREAM are supported. + + (This may fail on some Windows hosts where firewall software has cleverly + decided to keep 127.0.0.1 from talking to itself.) + + Parameters and return values are as for socketpair() +*/ +EVENT2_EXPORT_SYMBOL +int evutil_socketpair(int d, int type, int protocol, evutil_socket_t sv[2]); +/** Do platform-specific operations as needed to make a socket nonblocking. + + @param sock The socket to make nonblocking + @return 0 on success, -1 on failure + */ +EVENT2_EXPORT_SYMBOL +int evutil_make_socket_nonblocking(evutil_socket_t sock); + +/** Do platform-specific operations to make a listener socket reusable. + + Specifically, we want to make sure that another program will be able + to bind this address right after we've closed the listener. + + This differs from Windows's interpretation of "reusable", which + allows multiple listeners to bind the same address at the same time. + + @param sock The socket to make reusable + @return 0 on success, -1 on failure + */ +EVENT2_EXPORT_SYMBOL +int evutil_make_listen_socket_reuseable(evutil_socket_t sock); + +/** Do platform-specific operations to make a listener port reusable. + + Specifically, we want to make sure that multiple programs which also + set the same socket option will be able to bind, listen at the same time. + + This is a feature available only to Linux 3.9+ + + @param sock The socket to make reusable + @return 0 on success, -1 on failure + */ +EVENT2_EXPORT_SYMBOL +int evutil_make_listen_socket_reuseable_port(evutil_socket_t sock); + +/** Do platform-specific operations as needed to close a socket upon a + successful execution of one of the exec*() functions. + + @param sock The socket to be closed + @return 0 on success, -1 on failure + */ +EVENT2_EXPORT_SYMBOL +int evutil_make_socket_closeonexec(evutil_socket_t sock); + +/** Do the platform-specific call needed to close a socket returned from + socket() or accept(). + + @param sock The socket to be closed + @return 0 on success, -1 on failure + */ +EVENT2_EXPORT_SYMBOL +int evutil_closesocket(evutil_socket_t sock); +#define EVUTIL_CLOSESOCKET(s) evutil_closesocket(s) + +/** Do platform-specific operations, if possible, to make a tcp listener + * socket defer accept()s until there is data to read. + * + * Not all platforms support this. You don't want to do this for every + * listener socket: only the ones that implement a protocol where the + * client transmits before the server needs to respond. + * + * @param sock The listening socket to to make deferred + * @return 0 on success (whether the operation is supported or not), + * -1 on failure +*/ +EVENT2_EXPORT_SYMBOL +int evutil_make_tcp_listen_socket_deferred(evutil_socket_t sock); + +#ifdef _WIN32 +/** Return the most recent socket error. Not idempotent on all platforms. */ +#define EVUTIL_SOCKET_ERROR() WSAGetLastError() +/** Replace the most recent socket error with errcode */ +#define EVUTIL_SET_SOCKET_ERROR(errcode) \ + do { WSASetLastError(errcode); } while (0) +/** Return the most recent socket error to occur on sock. */ +EVENT2_EXPORT_SYMBOL +int evutil_socket_geterror(evutil_socket_t sock); +/** Convert a socket error to a string. */ +EVENT2_EXPORT_SYMBOL +const char *evutil_socket_error_to_string(int errcode); +#elif defined(EVENT_IN_DOXYGEN_) +/** + @name Socket error functions + + These functions are needed for making programs compatible between + Windows and Unix-like platforms. + + You see, Winsock handles socket errors differently from the rest of + the world. Elsewhere, a socket error is like any other error and is + stored in errno. But winsock functions require you to retrieve the + error with a special function, and don't let you use strerror for + the error codes. And handling EWOULDBLOCK is ... different. + + @{ +*/ +/** Return the most recent socket error. Not idempotent on all platforms. */ +#define EVUTIL_SOCKET_ERROR() ... +/** Replace the most recent socket error with errcode */ +#define EVUTIL_SET_SOCKET_ERROR(errcode) ... +/** Return the most recent socket error to occur on sock. */ +#define evutil_socket_geterror(sock) ... +/** Convert a socket error to a string. */ +#define evutil_socket_error_to_string(errcode) ... +/**@}*/ +#else +#define EVUTIL_SOCKET_ERROR() (errno) +#define EVUTIL_SET_SOCKET_ERROR(errcode) \ + do { errno = (errcode); } while (0) +#define evutil_socket_geterror(sock) (errno) +#define evutil_socket_error_to_string(errcode) (strerror(errcode)) +#endif + + +/** + * @name Manipulation macros for struct timeval. + * + * We define replacements + * for timeradd, timersub, timerclear, timercmp, and timerisset. + * + * @{ + */ +#ifdef EVENT__HAVE_TIMERADD +#define evutil_timeradd(tvp, uvp, vvp) timeradd((tvp), (uvp), (vvp)) +#define evutil_timersub(tvp, uvp, vvp) timersub((tvp), (uvp), (vvp)) +#else +#define evutil_timeradd(tvp, uvp, vvp) \ + do { \ + (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \ + (vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \ + if ((vvp)->tv_usec >= 1000000) { \ + (vvp)->tv_sec++; \ + (vvp)->tv_usec -= 1000000; \ + } \ + } while (0) +#define evutil_timersub(tvp, uvp, vvp) \ + do { \ + (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ + (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \ + if ((vvp)->tv_usec < 0) { \ + (vvp)->tv_sec--; \ + (vvp)->tv_usec += 1000000; \ + } \ + } while (0) +#endif /* !EVENT__HAVE_TIMERADD */ + +#ifdef EVENT__HAVE_TIMERCLEAR +#define evutil_timerclear(tvp) timerclear(tvp) +#else +#define evutil_timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 +#endif +/**@}*/ + +/** Return true iff the tvp is related to uvp according to the relational + * operator cmp. Recognized values for cmp are ==, <=, <, >=, and >. */ +#define evutil_timercmp(tvp, uvp, cmp) \ + (((tvp)->tv_sec == (uvp)->tv_sec) ? \ + ((tvp)->tv_usec cmp (uvp)->tv_usec) : \ + ((tvp)->tv_sec cmp (uvp)->tv_sec)) + +#ifdef EVENT__HAVE_TIMERISSET +#define evutil_timerisset(tvp) timerisset(tvp) +#else +#define evutil_timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) +#endif + +/** Replacement for offsetof on platforms that don't define it. */ +#ifdef offsetof +#define evutil_offsetof(type, field) offsetof(type, field) +#else +#define evutil_offsetof(type, field) ((off_t)(&((type *)0)->field)) +#endif + +/* big-int related functions */ +/** Parse a 64-bit value from a string. Arguments are as for strtol. */ +EVENT2_EXPORT_SYMBOL +ev_int64_t evutil_strtoll(const char *s, char **endptr, int base); + +/** Replacement for gettimeofday on platforms that lack it. */ +#ifdef EVENT__HAVE_GETTIMEOFDAY +#define evutil_gettimeofday(tv, tz) gettimeofday((tv), (tz)) +#else +struct timezone; +EVENT2_EXPORT_SYMBOL +int evutil_gettimeofday(struct timeval *tv, struct timezone *tz); +#endif + +/** Replacement for snprintf to get consistent behavior on platforms for + which the return value of snprintf does not conform to C99. + */ +EVENT2_EXPORT_SYMBOL +int evutil_snprintf(char *buf, size_t buflen, const char *format, ...) +#ifdef __GNUC__ + __attribute__((format(printf, 3, 4))) +#endif +; +/** Replacement for vsnprintf to get consistent behavior on platforms for + which the return value of snprintf does not conform to C99. + */ +EVENT2_EXPORT_SYMBOL +int evutil_vsnprintf(char *buf, size_t buflen, const char *format, va_list ap) +#ifdef __GNUC__ + __attribute__((format(printf, 3, 0))) +#endif +; + +/** Replacement for inet_ntop for platforms which lack it. */ +EVENT2_EXPORT_SYMBOL +const char *evutil_inet_ntop(int af, const void *src, char *dst, size_t len); +/** Replacement for inet_pton for platforms which lack it. */ +EVENT2_EXPORT_SYMBOL +int evutil_inet_pton(int af, const char *src, void *dst); +struct sockaddr; + +/** Parse an IPv4 or IPv6 address, with optional port, from a string. + + Recognized formats are: + - [IPv6Address]:port + - [IPv6Address] + - IPv6Address + - IPv4Address:port + - IPv4Address + + If no port is specified, the port in the output is set to 0. + + @param str The string to parse. + @param out A struct sockaddr to hold the result. This should probably be + a struct sockaddr_storage. + @param outlen A pointer to the number of bytes that that 'out' can safely + hold. Set to the number of bytes used in 'out' on success. + @return -1 if the address is not well-formed, if the port is out of range, + or if out is not large enough to hold the result. Otherwise returns + 0 on success. +*/ +EVENT2_EXPORT_SYMBOL +int evutil_parse_sockaddr_port(const char *str, struct sockaddr *out, int *outlen); + +/** Compare two sockaddrs; return 0 if they are equal, or less than 0 if sa1 + * preceeds sa2, or greater than 0 if sa1 follows sa2. If include_port is + * true, consider the port as well as the address. Only implemented for + * AF_INET and AF_INET6 addresses. The ordering is not guaranteed to remain + * the same between Libevent versions. */ +EVENT2_EXPORT_SYMBOL +int evutil_sockaddr_cmp(const struct sockaddr *sa1, const struct sockaddr *sa2, + int include_port); + +/** As strcasecmp, but always compares the characters in locale-independent + ASCII. That's useful if you're handling data in ASCII-based protocols. + */ +EVENT2_EXPORT_SYMBOL +int evutil_ascii_strcasecmp(const char *str1, const char *str2); +/** As strncasecmp, but always compares the characters in locale-independent + ASCII. That's useful if you're handling data in ASCII-based protocols. + */ +EVENT2_EXPORT_SYMBOL +int evutil_ascii_strncasecmp(const char *str1, const char *str2, size_t n); + +/* Here we define evutil_addrinfo to the native addrinfo type, or redefine it + * if this system has no getaddrinfo(). */ +#ifdef EVENT__HAVE_STRUCT_ADDRINFO +#define evutil_addrinfo addrinfo +#else +/** A definition of struct addrinfo for systems that lack it. + + (This is just an alias for struct addrinfo if the system defines + struct addrinfo.) +*/ +struct evutil_addrinfo { + int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */ + int ai_family; /* PF_xxx */ + int ai_socktype; /* SOCK_xxx */ + int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ + size_t ai_addrlen; /* length of ai_addr */ + char *ai_canonname; /* canonical name for nodename */ + struct sockaddr *ai_addr; /* binary address */ + struct evutil_addrinfo *ai_next; /* next structure in linked list */ +}; +#endif +/** @name evutil_getaddrinfo() error codes + + These values are possible error codes for evutil_getaddrinfo() and + related functions. + + @{ +*/ +#if defined(EAI_ADDRFAMILY) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_EAI_ADDRFAMILY EAI_ADDRFAMILY +#else +#define EVUTIL_EAI_ADDRFAMILY -901 +#endif +#if defined(EAI_AGAIN) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_EAI_AGAIN EAI_AGAIN +#else +#define EVUTIL_EAI_AGAIN -902 +#endif +#if defined(EAI_BADFLAGS) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_EAI_BADFLAGS EAI_BADFLAGS +#else +#define EVUTIL_EAI_BADFLAGS -903 +#endif +#if defined(EAI_FAIL) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_EAI_FAIL EAI_FAIL +#else +#define EVUTIL_EAI_FAIL -904 +#endif +#if defined(EAI_FAMILY) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_EAI_FAMILY EAI_FAMILY +#else +#define EVUTIL_EAI_FAMILY -905 +#endif +#if defined(EAI_MEMORY) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_EAI_MEMORY EAI_MEMORY +#else +#define EVUTIL_EAI_MEMORY -906 +#endif +/* This test is a bit complicated, since some MS SDKs decide to + * remove NODATA or redefine it to be the same as NONAME, in a + * fun interpretation of RFC 2553 and RFC 3493. */ +#if defined(EAI_NODATA) && defined(EVENT__HAVE_GETADDRINFO) && (!defined(EAI_NONAME) || EAI_NODATA != EAI_NONAME) +#define EVUTIL_EAI_NODATA EAI_NODATA +#else +#define EVUTIL_EAI_NODATA -907 +#endif +#if defined(EAI_NONAME) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_EAI_NONAME EAI_NONAME +#else +#define EVUTIL_EAI_NONAME -908 +#endif +#if defined(EAI_SERVICE) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_EAI_SERVICE EAI_SERVICE +#else +#define EVUTIL_EAI_SERVICE -909 +#endif +#if defined(EAI_SOCKTYPE) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_EAI_SOCKTYPE EAI_SOCKTYPE +#else +#define EVUTIL_EAI_SOCKTYPE -910 +#endif +#if defined(EAI_SYSTEM) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_EAI_SYSTEM EAI_SYSTEM +#else +#define EVUTIL_EAI_SYSTEM -911 +#endif + +#define EVUTIL_EAI_CANCEL -90001 + +#if defined(AI_PASSIVE) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_AI_PASSIVE AI_PASSIVE +#else +#define EVUTIL_AI_PASSIVE 0x1000 +#endif +#if defined(AI_CANONNAME) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_AI_CANONNAME AI_CANONNAME +#else +#define EVUTIL_AI_CANONNAME 0x2000 +#endif +#if defined(AI_NUMERICHOST) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_AI_NUMERICHOST AI_NUMERICHOST +#else +#define EVUTIL_AI_NUMERICHOST 0x4000 +#endif +#if defined(AI_NUMERICSERV) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_AI_NUMERICSERV AI_NUMERICSERV +#else +#define EVUTIL_AI_NUMERICSERV 0x8000 +#endif +#if defined(AI_V4MAPPED) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_AI_V4MAPPED AI_V4MAPPED +#else +#define EVUTIL_AI_V4MAPPED 0x10000 +#endif +#if defined(AI_ALL) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_AI_ALL AI_ALL +#else +#define EVUTIL_AI_ALL 0x20000 +#endif +#if defined(AI_ADDRCONFIG) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_AI_ADDRCONFIG AI_ADDRCONFIG +#else +#define EVUTIL_AI_ADDRCONFIG 0x40000 +#endif +/**@}*/ + +struct evutil_addrinfo; +/** + * This function clones getaddrinfo for systems that don't have it. For full + * details, see RFC 3493, section 6.1. + * + * Limitations: + * - When the system has no getaddrinfo, we fall back to gethostbyname_r or + * gethostbyname, with their attendant issues. + * - The AI_V4MAPPED and AI_ALL flags are not currently implemented. + * + * For a nonblocking variant, see evdns_getaddrinfo. + */ +EVENT2_EXPORT_SYMBOL +int evutil_getaddrinfo(const char *nodename, const char *servname, + const struct evutil_addrinfo *hints_in, struct evutil_addrinfo **res); + +/** Release storage allocated by evutil_getaddrinfo or evdns_getaddrinfo. */ +EVENT2_EXPORT_SYMBOL +void evutil_freeaddrinfo(struct evutil_addrinfo *ai); + +EVENT2_EXPORT_SYMBOL +const char *evutil_gai_strerror(int err); + +/** Generate n bytes of secure pseudorandom data, and store them in buf. + * + * Current versions of Libevent use an ARC4-based random number generator, + * seeded using the platform's entropy source (/dev/urandom on Unix-like + * systems; CryptGenRandom on Windows). This is not actually as secure as it + * should be: ARC4 is a pretty lousy cipher, and the current implementation + * provides only rudimentary prediction- and backtracking-resistance. Don't + * use this for serious cryptographic applications. + */ +EVENT2_EXPORT_SYMBOL +void evutil_secure_rng_get_bytes(void *buf, size_t n); + +/** + * Seed the secure random number generator if needed, and return 0 on + * success or -1 on failure. + * + * It is okay to call this function more than once; it will still return + * 0 if the RNG has been successfully seeded and -1 if it can't be + * seeded. + * + * Ordinarily you don't need to call this function from your own code; + * Libevent will seed the RNG itself the first time it needs good random + * numbers. You only need to call it if (a) you want to double-check + * that one of the seeding methods did succeed, or (b) you plan to drop + * the capability to seed (by chrooting, or dropping capabilities, or + * whatever), and you want to make sure that seeding happens before your + * program loses the ability to do it. + */ +EVENT2_EXPORT_SYMBOL +int evutil_secure_rng_init(void); + +/** + * Set a filename to use in place of /dev/urandom for seeding the secure + * PRNG. Return 0 on success, -1 on failure. + * + * Call this function BEFORE calling any other initialization or RNG + * functions. + * + * (This string will _NOT_ be copied internally. Do not free it while any + * user of the secure RNG might be running. Don't pass anything other than a + * real /dev/...random device file here, or you might lose security.) + * + * This API is unstable, and might change in a future libevent version. + */ +EVENT2_EXPORT_SYMBOL +int evutil_secure_rng_set_urandom_device_file(char *fname); + +/** Seed the random number generator with extra random bytes. + + You should almost never need to call this function; it should be + sufficient to invoke evutil_secure_rng_init(), or let Libevent take + care of calling evutil_secure_rng_init() on its own. + + If you call this function as a _replacement_ for the regular + entropy sources, then you need to be sure that your input + contains a fairly large amount of strong entropy. Doing so is + notoriously hard: most people who try get it wrong. Watch out! + + @param dat a buffer full of a strong source of random numbers + @param datlen the number of bytes to read from datlen + */ +EVENT2_EXPORT_SYMBOL +void evutil_secure_rng_add_bytes(const char *dat, size_t datlen); + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT1_EVUTIL_H_INCLUDED_ */ diff --git a/src/include/event2/visibility.h b/src/include/event2/visibility.h new file mode 100644 index 0000000..fb16dbe --- /dev/null +++ b/src/include/event2/visibility.h @@ -0,0 +1,50 @@ +/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EVENT2_VISIBILITY_H_INCLUDED_ +#define EVENT2_VISIBILITY_H_INCLUDED_ + +#include <event2/event-config.h> + +#if defined(event_EXPORTS) || defined(event_extra_EXPORTS) || defined(event_core_EXPORTS) +# if defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550) +# define EVENT2_EXPORT_SYMBOL __global +# elif defined __GNUC__ +# define EVENT2_EXPORT_SYMBOL __attribute__ ((visibility("default"))) +# elif defined(_MSC_VER) +# define EVENT2_EXPORT_SYMBOL extern __declspec(dllexport) +# else +# define EVENT2_EXPORT_SYMBOL /* unknown compiler */ +# endif +#else +# if defined(EVENT__NEED_DLLIMPORT) && defined(_MSC_VER) && !defined(EVENT_BUILDING_REGRESS_TEST) +# define EVENT2_EXPORT_SYMBOL extern __declspec(dllimport) +# else +# define EVENT2_EXPORT_SYMBOL +# endif +#endif + +#endif /* EVENT2_VISIBILITY_H_INCLUDED_ */ diff --git a/src/include/evhttp.h b/src/include/evhttp.h new file mode 100644 index 0000000..549bc9b --- /dev/null +++ b/src/include/evhttp.h @@ -0,0 +1,45 @@ +/* + * Copyright 2000-2007 Niels Provos <[email protected]> + * Copyright 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EVENT1_EVHTTP_H_INCLUDED_ +#define EVENT1_EVHTTP_H_INCLUDED_ + +/** @file evhttp.h + + An http implementation subsystem for Libevent. + + The <evhttp.h> header is deprecated in Libevent 2.0 and later; please + use <event2/http.h> instead. Depending on what functionality you + need, you may also want to include more of the other <event2/...> + headers. + */ + +#include <event.h> +#include <event2/http.h> +#include <event2/http_struct.h> +#include <event2/http_compat.h> + +#endif /* EVENT1_EVHTTP_H_INCLUDED_ */ diff --git a/src/include/evrpc.h b/src/include/evrpc.h new file mode 100644 index 0000000..7e986f7 --- /dev/null +++ b/src/include/evrpc.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2000-2007 Niels Provos <[email protected]> + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EVENT1_EVRPC_H_INCLUDED_ +#define EVENT1_EVRPC_H_INCLUDED_ + +/** @file evrpc.h + + An RPC system for Libevent. + + The <evrpc.h> header is deprecated in Libevent 2.0 and later; please + use <event2/rpc.h> instead. Depending on what functionality you + need, you may also want to include more of the other <event2/...> + headers. + */ + +#include <event.h> +#include <event2/rpc.h> +#include <event2/rpc_struct.h> +#include <event2/rpc_compat.h> + +#endif /* EVENT1_EVRPC_H_INCLUDED_ */ diff --git a/src/include/evutil.h b/src/include/evutil.h new file mode 100644 index 0000000..12c137d --- /dev/null +++ b/src/include/evutil.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EVENT1_EVUTIL_H_INCLUDED_ +#define EVENT1_EVUTIL_H_INCLUDED_ + +/** @file evutil.h + + Utility and compatibility functions for Libevent. + + The <evutil.h> header is deprecated in Libevent 2.0 and later; please + use <event2/util.h> instead. +*/ + +#include <event2/util.h> + +#endif /* EVENT1_EVUTIL_H_INCLUDED_ */ diff --git a/src/include/librdkafka/rdkafka.h b/src/include/librdkafka/rdkafka.h new file mode 100644 index 0000000..16770dc --- /dev/null +++ b/src/include/librdkafka/rdkafka.h @@ -0,0 +1,4190 @@ +/* + * librdkafka - Apache Kafka C library + * + * Copyright (c) 2012-2013 Magnus Edenhill + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file rdkafka.h + * @brief Apache Kafka C/C++ consumer and producer client library. + * + * rdkafka.h contains the public API for librdkafka. + * The API is documented in this file as comments prefixing the function, type, + * enum, define, etc. + * + * @sa For the C++ interface see rdkafkacpp.h + * + * @tableofcontents + */ + + +/* @cond NO_DOC */ +#pragma once + +#include <stdio.h> +#include <inttypes.h> +#include <sys/types.h> + +#ifdef __cplusplus +extern "C" { +#if 0 +} /* Restore indent */ +#endif +#endif + +#ifdef _MSC_VER +#include <basetsd.h> +#ifndef WIN32_MEAN_AND_LEAN +#define WIN32_MEAN_AND_LEAN +#endif +#include <Winsock2.h> /* for sockaddr, .. */ +typedef SSIZE_T ssize_t; +#define RD_UNUSED +#define RD_INLINE __inline +#define RD_DEPRECATED __declspec(deprecated) +#undef RD_EXPORT +#ifdef LIBRDKAFKA_STATICLIB +#define RD_EXPORT +#else +#ifdef LIBRDKAFKA_EXPORTS +#define RD_EXPORT __declspec(dllexport) +#else +#define RD_EXPORT __declspec(dllimport) +#endif +#ifndef LIBRDKAFKA_TYPECHECKS +#define LIBRDKAFKA_TYPECHECKS 0 +#endif +#endif + +#else +#include <sys/socket.h> /* for sockaddr, .. */ + +#define RD_UNUSED __attribute__((unused)) +#define RD_INLINE inline +#define RD_EXPORT +#define RD_DEPRECATED __attribute__((deprecated)) + +#ifndef LIBRDKAFKA_TYPECHECKS +#define LIBRDKAFKA_TYPECHECKS 1 +#endif +#endif + + +/** + * @brief Type-checking macros + * Compile-time checking that \p ARG is of type \p TYPE. + * @returns \p RET + */ +#if LIBRDKAFKA_TYPECHECKS +#define _LRK_TYPECHECK(RET,TYPE,ARG) \ + ({ if (0) { TYPE __t RD_UNUSED = (ARG); } RET; }) + +#define _LRK_TYPECHECK2(RET,TYPE,ARG,TYPE2,ARG2) \ + ({ \ + if (0) { \ + TYPE __t RD_UNUSED = (ARG); \ + TYPE2 __t2 RD_UNUSED = (ARG2); \ + } \ + RET; }) + +#define _LRK_TYPECHECK3(RET,TYPE,ARG,TYPE2,ARG2,TYPE3,ARG3) \ + ({ \ + if (0) { \ + TYPE __t RD_UNUSED = (ARG); \ + TYPE2 __t2 RD_UNUSED = (ARG2); \ + TYPE3 __t3 RD_UNUSED = (ARG3); \ + } \ + RET; }) +#else +#define _LRK_TYPECHECK(RET,TYPE,ARG) (RET) +#define _LRK_TYPECHECK2(RET,TYPE,ARG,TYPE2,ARG2) (RET) +#define _LRK_TYPECHECK3(RET,TYPE,ARG,TYPE2,ARG2,TYPE3,ARG3) (RET) +#endif + +/* @endcond */ + + +/** + * @name librdkafka version + * @{ + * + * + */ + +/** + * @brief librdkafka version + * + * Interpreted as hex \c MM.mm.rr.xx: + * - MM = Major + * - mm = minor + * - rr = revision + * - xx = pre-release id (0xff is the final release) + * + * E.g.: \c 0x000801ff = 0.8.1 + * + * @remark This value should only be used during compile time, + * for runtime checks of version use rd_kafka_version() + */ +#define RD_KAFKA_VERSION 0x000b01ff + +/** + * @brief Returns the librdkafka version as integer. + * + * @returns Version integer. + * + * @sa See RD_KAFKA_VERSION for how to parse the integer format. + * @sa Use rd_kafka_version_str() to retreive the version as a string. + */ +RD_EXPORT +int rd_kafka_version(void); + +/** + * @brief Returns the librdkafka version as string. + * + * @returns Version string + */ +RD_EXPORT +const char *rd_kafka_version_str (void); + +/**@}*/ + + +/** + * @name Constants, errors, types + * @{ + * + * + */ + + +/** + * @enum rd_kafka_type_t + * + * @brief rd_kafka_t handle type. + * + * @sa rd_kafka_new() + */ +typedef enum rd_kafka_type_t { + RD_KAFKA_PRODUCER, /**< Producer client */ + RD_KAFKA_CONSUMER /**< Consumer client */ +} rd_kafka_type_t; + + +/** + * @enum Timestamp types + * + * @sa rd_kafka_message_timestamp() + */ +typedef enum rd_kafka_timestamp_type_t { + RD_KAFKA_TIMESTAMP_NOT_AVAILABLE, /**< Timestamp not available */ + RD_KAFKA_TIMESTAMP_CREATE_TIME, /**< Message creation time */ + RD_KAFKA_TIMESTAMP_LOG_APPEND_TIME /**< Log append time */ +} rd_kafka_timestamp_type_t; + + + +/** + * @brief Retrieve supported debug contexts for use with the \c \"debug\" + * configuration property. (runtime) + * + * @returns Comma-separated list of available debugging contexts. + */ +RD_EXPORT +const char *rd_kafka_get_debug_contexts(void); + +/** + * @brief Supported debug contexts. (compile time) + * + * @deprecated This compile time value may be outdated at runtime due to + * linking another version of the library. + * Use rd_kafka_get_debug_contexts() instead. + */ +#define RD_KAFKA_DEBUG_CONTEXTS \ + "all,generic,broker,topic,metadata,feature,queue,msg,protocol,cgrp,security,fetch,interceptor,plugin,consumer" + + +/* @cond NO_DOC */ +/* Private types to provide ABI compatibility */ +typedef struct rd_kafka_s rd_kafka_t; +typedef struct rd_kafka_topic_s rd_kafka_topic_t; +typedef struct rd_kafka_conf_s rd_kafka_conf_t; +typedef struct rd_kafka_topic_conf_s rd_kafka_topic_conf_t; +typedef struct rd_kafka_queue_s rd_kafka_queue_t; +/* @endcond */ + + +/** + * @enum rd_kafka_resp_err_t + * @brief Error codes. + * + * The negative error codes delimited by two underscores + * (\c RD_KAFKA_RESP_ERR__..) denotes errors internal to librdkafka and are + * displayed as \c \"Local: \<error string..\>\", while the error codes + * delimited by a single underscore (\c RD_KAFKA_RESP_ERR_..) denote broker + * errors and are displayed as \c \"Broker: \<error string..\>\". + * + * @sa Use rd_kafka_err2str() to translate an error code a human readable string + */ +typedef enum { + /* Internal errors to rdkafka: */ + /** Begin internal error codes */ + RD_KAFKA_RESP_ERR__BEGIN = -200, + /** Received message is incorrect */ + RD_KAFKA_RESP_ERR__BAD_MSG = -199, + /** Bad/unknown compression */ + RD_KAFKA_RESP_ERR__BAD_COMPRESSION = -198, + /** Broker is going away */ + RD_KAFKA_RESP_ERR__DESTROY = -197, + /** Generic failure */ + RD_KAFKA_RESP_ERR__FAIL = -196, + /** Broker transport failure */ + RD_KAFKA_RESP_ERR__TRANSPORT = -195, + /** Critical system resource */ + RD_KAFKA_RESP_ERR__CRIT_SYS_RESOURCE = -194, + /** Failed to resolve broker */ + RD_KAFKA_RESP_ERR__RESOLVE = -193, + /** Produced message timed out*/ + RD_KAFKA_RESP_ERR__MSG_TIMED_OUT = -192, + /** Reached the end of the topic+partition queue on + * the broker. Not really an error. */ + RD_KAFKA_RESP_ERR__PARTITION_EOF = -191, + /** Permanent: Partition does not exist in cluster. */ + RD_KAFKA_RESP_ERR__UNKNOWN_PARTITION = -190, + /** File or filesystem error */ + RD_KAFKA_RESP_ERR__FS = -189, + /** Permanent: Topic does not exist in cluster. */ + RD_KAFKA_RESP_ERR__UNKNOWN_TOPIC = -188, + /** All broker connections are down. */ + RD_KAFKA_RESP_ERR__ALL_BROKERS_DOWN = -187, + /** Invalid argument, or invalid configuration */ + RD_KAFKA_RESP_ERR__INVALID_ARG = -186, + /** Operation timed out */ + RD_KAFKA_RESP_ERR__TIMED_OUT = -185, + /** Queue is full */ + RD_KAFKA_RESP_ERR__QUEUE_FULL = -184, + /** ISR count < required.acks */ + RD_KAFKA_RESP_ERR__ISR_INSUFF = -183, + /** Broker node update */ + RD_KAFKA_RESP_ERR__NODE_UPDATE = -182, + /** SSL error */ + RD_KAFKA_RESP_ERR__SSL = -181, + /** Waiting for coordinator to become available. */ + RD_KAFKA_RESP_ERR__WAIT_COORD = -180, + /** Unknown client group */ + RD_KAFKA_RESP_ERR__UNKNOWN_GROUP = -179, + /** Operation in progress */ + RD_KAFKA_RESP_ERR__IN_PROGRESS = -178, + /** Previous operation in progress, wait for it to finish. */ + RD_KAFKA_RESP_ERR__PREV_IN_PROGRESS = -177, + /** This operation would interfere with an existing subscription */ + RD_KAFKA_RESP_ERR__EXISTING_SUBSCRIPTION = -176, + /** Assigned partitions (kafka_rebalance_cb) */ + RD_KAFKA_RESP_ERR__ASSIGN_PARTITIONS = -175, + /** Revoked partitions (rebalance_cb) */ + RD_KAFKA_RESP_ERR__REVOKE_PARTITIONS = -174, + /** Conflicting use */ + RD_KAFKA_RESP_ERR__CONFLICT = -173, + /** Wrong state */ + RD_KAFKA_RESP_ERR__STATE = -172, + /** Unknown protocol */ + RD_KAFKA_RESP_ERR__UNKNOWN_PROTOCOL = -171, + /** Not implemented */ + RD_KAFKA_RESP_ERR__NOT_IMPLEMENTED = -170, + /** Authentication failure*/ + RD_KAFKA_RESP_ERR__AUTHENTICATION = -169, + /** No stored offset */ + RD_KAFKA_RESP_ERR__NO_OFFSET = -168, + /** Outdated */ + RD_KAFKA_RESP_ERR__OUTDATED = -167, + /** Timed out in queue */ + RD_KAFKA_RESP_ERR__TIMED_OUT_QUEUE = -166, + /** Feature not supported by broker */ + RD_KAFKA_RESP_ERR__UNSUPPORTED_FEATURE = -165, + /** Awaiting cache update */ + RD_KAFKA_RESP_ERR__WAIT_CACHE = -164, + /** Operation interrupted (e.g., due to yield)) */ + RD_KAFKA_RESP_ERR__INTR = -163, + /** Key serialization error */ + RD_KAFKA_RESP_ERR__KEY_SERIALIZATION = -162, + /** Value serialization error */ + RD_KAFKA_RESP_ERR__VALUE_SERIALIZATION = -161, + /** Key deserialization error */ + RD_KAFKA_RESP_ERR__KEY_DESERIALIZATION = -160, + /** Value deserialization error */ + RD_KAFKA_RESP_ERR__VALUE_DESERIALIZATION = -159, + /** Partial response */ + RD_KAFKA_RESP_ERR__PARTIAL = -158, + /** Modification attempted on read-only object */ + RD_KAFKA_RESP_ERR__READ_ONLY = -157, + /** No such entry / item not found */ + RD_KAFKA_RESP_ERR__NOENT = -156, + /** Read underflow */ + RD_KAFKA_RESP_ERR__UNDERFLOW = -155, + + /** End internal error codes */ + RD_KAFKA_RESP_ERR__END = -100, + + /* Kafka broker errors: */ + /** Unknown broker error */ + RD_KAFKA_RESP_ERR_UNKNOWN = -1, + /** Success */ + RD_KAFKA_RESP_ERR_NO_ERROR = 0, + /** Offset out of range */ + RD_KAFKA_RESP_ERR_OFFSET_OUT_OF_RANGE = 1, + /** Invalid message */ + RD_KAFKA_RESP_ERR_INVALID_MSG = 2, + /** Unknown topic or partition */ + RD_KAFKA_RESP_ERR_UNKNOWN_TOPIC_OR_PART = 3, + /** Invalid message size */ + RD_KAFKA_RESP_ERR_INVALID_MSG_SIZE = 4, + /** Leader not available */ + RD_KAFKA_RESP_ERR_LEADER_NOT_AVAILABLE = 5, + /** Not leader for partition */ + RD_KAFKA_RESP_ERR_NOT_LEADER_FOR_PARTITION = 6, + /** Request timed out */ + RD_KAFKA_RESP_ERR_REQUEST_TIMED_OUT = 7, + /** Broker not available */ + RD_KAFKA_RESP_ERR_BROKER_NOT_AVAILABLE = 8, + /** Replica not available */ + RD_KAFKA_RESP_ERR_REPLICA_NOT_AVAILABLE = 9, + /** Message size too large */ + RD_KAFKA_RESP_ERR_MSG_SIZE_TOO_LARGE = 10, + /** StaleControllerEpochCode */ + RD_KAFKA_RESP_ERR_STALE_CTRL_EPOCH = 11, + /** Offset metadata string too large */ + RD_KAFKA_RESP_ERR_OFFSET_METADATA_TOO_LARGE = 12, + /** Broker disconnected before response received */ + RD_KAFKA_RESP_ERR_NETWORK_EXCEPTION = 13, + /** Group coordinator load in progress */ + RD_KAFKA_RESP_ERR_GROUP_LOAD_IN_PROGRESS = 14, + /** Group coordinator not available */ + RD_KAFKA_RESP_ERR_GROUP_COORDINATOR_NOT_AVAILABLE = 15, + /** Not coordinator for group */ + RD_KAFKA_RESP_ERR_NOT_COORDINATOR_FOR_GROUP = 16, + /** Invalid topic */ + RD_KAFKA_RESP_ERR_TOPIC_EXCEPTION = 17, + /** Message batch larger than configured server segment size */ + RD_KAFKA_RESP_ERR_RECORD_LIST_TOO_LARGE = 18, + /** Not enough in-sync replicas */ + RD_KAFKA_RESP_ERR_NOT_ENOUGH_REPLICAS = 19, + /** Message(s) written to insufficient number of in-sync replicas */ + RD_KAFKA_RESP_ERR_NOT_ENOUGH_REPLICAS_AFTER_APPEND = 20, + /** Invalid required acks value */ + RD_KAFKA_RESP_ERR_INVALID_REQUIRED_ACKS = 21, + /** Specified group generation id is not valid */ + RD_KAFKA_RESP_ERR_ILLEGAL_GENERATION = 22, + /** Inconsistent group protocol */ + RD_KAFKA_RESP_ERR_INCONSISTENT_GROUP_PROTOCOL = 23, + /** Invalid group.id */ + RD_KAFKA_RESP_ERR_INVALID_GROUP_ID = 24, + /** Unknown member */ + RD_KAFKA_RESP_ERR_UNKNOWN_MEMBER_ID = 25, + /** Invalid session timeout */ + RD_KAFKA_RESP_ERR_INVALID_SESSION_TIMEOUT = 26, + /** Group rebalance in progress */ + RD_KAFKA_RESP_ERR_REBALANCE_IN_PROGRESS = 27, + /** Commit offset data size is not valid */ + RD_KAFKA_RESP_ERR_INVALID_COMMIT_OFFSET_SIZE = 28, + /** Topic authorization failed */ + RD_KAFKA_RESP_ERR_TOPIC_AUTHORIZATION_FAILED = 29, + /** Group authorization failed */ + RD_KAFKA_RESP_ERR_GROUP_AUTHORIZATION_FAILED = 30, + /** Cluster authorization failed */ + RD_KAFKA_RESP_ERR_CLUSTER_AUTHORIZATION_FAILED = 31, + /** Invalid timestamp */ + RD_KAFKA_RESP_ERR_INVALID_TIMESTAMP = 32, + /** Unsupported SASL mechanism */ + RD_KAFKA_RESP_ERR_UNSUPPORTED_SASL_MECHANISM = 33, + /** Illegal SASL state */ + RD_KAFKA_RESP_ERR_ILLEGAL_SASL_STATE = 34, + /** Unuspported version */ + RD_KAFKA_RESP_ERR_UNSUPPORTED_VERSION = 35, + /** Topic already exists */ + RD_KAFKA_RESP_ERR_TOPIC_ALREADY_EXISTS = 36, + /** Invalid number of partitions */ + RD_KAFKA_RESP_ERR_INVALID_PARTITIONS = 37, + /** Invalid replication factor */ + RD_KAFKA_RESP_ERR_INVALID_REPLICATION_FACTOR = 38, + /** Invalid replica assignment */ + RD_KAFKA_RESP_ERR_INVALID_REPLICA_ASSIGNMENT = 39, + /** Invalid config */ + RD_KAFKA_RESP_ERR_INVALID_CONFIG = 40, + /** Not controller for cluster */ + RD_KAFKA_RESP_ERR_NOT_CONTROLLER = 41, + /** Invalid request */ + RD_KAFKA_RESP_ERR_INVALID_REQUEST = 42, + /** Message format on broker does not support request */ + RD_KAFKA_RESP_ERR_UNSUPPORTED_FOR_MESSAGE_FORMAT = 43, + /** Isolation policy volation */ + RD_KAFKA_RESP_ERR_POLICY_VIOLATION = 44, + /** Broker received an out of order sequence number */ + RD_KAFKA_RESP_ERR_OUT_OF_ORDER_SEQUENCE_NUMBER = 45, + /** Broker received a duplicate sequence number */ + RD_KAFKA_RESP_ERR_DUPLICATE_SEQUENCE_NUMBER = 46, + /** Producer attempted an operation with an old epoch */ + RD_KAFKA_RESP_ERR_INVALID_PRODUCER_EPOCH = 47, + /** Producer attempted a transactional operation in an invalid state */ + RD_KAFKA_RESP_ERR_INVALID_TXN_STATE = 48, + /** Producer attempted to use a producer id which is not + * currently assigned to its transactional id */ + RD_KAFKA_RESP_ERR_INVALID_PRODUCER_ID_MAPPING = 49, + /** Transaction timeout is larger than the maximum + * value allowed by the broker's max.transaction.timeout.ms */ + RD_KAFKA_RESP_ERR_INVALID_TRANSACTION_TIMEOUT = 50, + /** Producer attempted to update a transaction while another + * concurrent operation on the same transaction was ongoing */ + RD_KAFKA_RESP_ERR_CONCURRENT_TRANSACTIONS = 51, + /** Indicates that the transaction coordinator sending a + * WriteTxnMarker is no longer the current coordinator for a + * given producer */ + RD_KAFKA_RESP_ERR_TRANSACTION_COORDINATOR_FENCED = 52, + /** Transactional Id authorization failed */ + RD_KAFKA_RESP_ERR_TRANSACTIONAL_ID_AUTHORIZATION_FAILED = 53, + /** Security features are disabled */ + RD_KAFKA_RESP_ERR_SECURITY_DISABLED = 54, + /** Operation not attempted */ + RD_KAFKA_RESP_ERR_OPERATION_NOT_ATTEMPTED = 55, + + RD_KAFKA_RESP_ERR_END_ALL, +} rd_kafka_resp_err_t; + + +/** + * @brief Error code value, name and description. + * Typically for use with language bindings to automatically expose + * the full set of librdkafka error codes. + */ +struct rd_kafka_err_desc { + rd_kafka_resp_err_t code;/**< Error code */ + const char *name; /**< Error name, same as code enum sans prefix */ + const char *desc; /**< Human readable error description. */ +}; + + +/** + * @brief Returns the full list of error codes. + */ +RD_EXPORT +void rd_kafka_get_err_descs (const struct rd_kafka_err_desc **errdescs, + size_t *cntp); + + + + +/** + * @brief Returns a human readable representation of a kafka error. + * + * @param err Error code to translate + */ +RD_EXPORT +const char *rd_kafka_err2str (rd_kafka_resp_err_t err); + + + +/** + * @brief Returns the error code name (enum name). + * + * @param err Error code to translate + */ +RD_EXPORT +const char *rd_kafka_err2name (rd_kafka_resp_err_t err); + + +/** + * @brief Returns the last error code generated by a legacy API call + * in the current thread. + * + * The legacy APIs are the ones using errno to propagate error value, namely: + * - rd_kafka_topic_new() + * - rd_kafka_consume_start() + * - rd_kafka_consume_stop() + * - rd_kafka_consume() + * - rd_kafka_consume_batch() + * - rd_kafka_consume_callback() + * - rd_kafka_consume_queue() + * - rd_kafka_produce() + * + * The main use for this function is to avoid converting system \p errno + * values to rd_kafka_resp_err_t codes for legacy APIs. + * + * @remark The last error is stored per-thread, if multiple rd_kafka_t handles + * are used in the same application thread the developer needs to + * make sure rd_kafka_last_error() is called immediately after + * a failed API call. + * + * @remark errno propagation from librdkafka is not safe on Windows + * and should not be used, use rd_kafka_last_error() instead. + */ +RD_EXPORT +rd_kafka_resp_err_t rd_kafka_last_error (void); + + +/** + * @brief Converts the system errno value \p errnox to a rd_kafka_resp_err_t + * error code upon failure from the following functions: + * - rd_kafka_topic_new() + * - rd_kafka_consume_start() + * - rd_kafka_consume_stop() + * - rd_kafka_consume() + * - rd_kafka_consume_batch() + * - rd_kafka_consume_callback() + * - rd_kafka_consume_queue() + * - rd_kafka_produce() + * + * @param errnox System errno value to convert + * + * @returns Appropriate error code for \p errnox + * + * @remark A better alternative is to call rd_kafka_last_error() immediately + * after any of the above functions return -1 or NULL. + * + * @deprecated Use rd_kafka_last_error() to retrieve the last error code + * set by the legacy librdkafka APIs. + * + * @sa rd_kafka_last_error() + */ +RD_EXPORT RD_DEPRECATED +rd_kafka_resp_err_t rd_kafka_errno2err(int errnox); + + +/** + * @brief Returns the thread-local system errno + * + * On most platforms this is the same as \p errno but in case of different + * runtimes between library and application (e.g., Windows static DLLs) + * this provides a means for exposing the errno librdkafka uses. + * + * @remark The value is local to the current calling thread. + * + * @deprecated Use rd_kafka_last_error() to retrieve the last error code + * set by the legacy librdkafka APIs. + */ +RD_EXPORT RD_DEPRECATED +int rd_kafka_errno (void); + + + +/** + * @brief Topic+Partition place holder + * + * Generic place holder for a Topic+Partition and its related information + * used for multiple purposes: + * - consumer offset (see rd_kafka_commit(), et.al.) + * - group rebalancing callback (rd_kafka_conf_set_rebalance_cb()) + * - offset commit result callback (rd_kafka_conf_set_offset_commit_cb()) + */ + +/** + * @brief Generic place holder for a specific Topic+Partition. + * + * @sa rd_kafka_topic_partition_list_new() + */ +typedef struct rd_kafka_topic_partition_s { + char *topic; /**< Topic name */ + int32_t partition; /**< Partition */ + int64_t offset; /**< Offset */ + void *metadata; /**< Metadata */ + size_t metadata_size; /**< Metadata size */ + void *opaque; /**< Application opaque */ + rd_kafka_resp_err_t err; /**< Error code, depending on use. */ + void *_private; /**< INTERNAL USE ONLY, + * INITIALIZE TO ZERO, DO NOT TOUCH */ +} rd_kafka_topic_partition_t; + + +/** + * @brief Destroy a rd_kafka_topic_partition_t. + * @remark This must not be called for elements in a topic partition list. + */ +RD_EXPORT +void rd_kafka_topic_partition_destroy (rd_kafka_topic_partition_t *rktpar); + + +/** + * @brief A growable list of Topic+Partitions. + * + */ +typedef struct rd_kafka_topic_partition_list_s { + int cnt; /**< Current number of elements */ + int size; /**< Current allocated size */ + rd_kafka_topic_partition_t *elems; /**< Element array[] */ +} rd_kafka_topic_partition_list_t; + + +/** + * @brief Create a new list/vector Topic+Partition container. + * + * @param size Initial allocated size used when the expected number of + * elements is known or can be estimated. + * Avoids reallocation and possibly relocation of the + * elems array. + * + * @returns A newly allocated Topic+Partition list. + * + * @remark Use rd_kafka_topic_partition_list_destroy() to free all resources + * in use by a list and the list itself. + * @sa rd_kafka_topic_partition_list_add() + */ +RD_EXPORT +rd_kafka_topic_partition_list_t *rd_kafka_topic_partition_list_new (int size); + + +/** + * @brief Free all resources used by the list and the list itself. + */ +RD_EXPORT +void +rd_kafka_topic_partition_list_destroy (rd_kafka_topic_partition_list_t *rkparlist); + +/** + * @brief Add topic+partition to list + * + * @param rktparlist List to extend + * @param topic Topic name (copied) + * @param partition Partition id + * + * @returns The object which can be used to fill in additionals fields. + */ +RD_EXPORT +rd_kafka_topic_partition_t * +rd_kafka_topic_partition_list_add (rd_kafka_topic_partition_list_t *rktparlist, + const char *topic, int32_t partition); + + +/** + * @brief Add range of partitions from \p start to \p stop inclusive. + * + * @param rktparlist List to extend + * @param topic Topic name (copied) + * @param start Start partition of range + * @param stop Last partition of range (inclusive) + */ +RD_EXPORT +void +rd_kafka_topic_partition_list_add_range (rd_kafka_topic_partition_list_t + *rktparlist, + const char *topic, + int32_t start, int32_t stop); + + + +/** + * @brief Delete partition from list. + * + * @param rktparlist List to modify + * @param topic Topic name to match + * @param partition Partition to match + * + * @returns 1 if partition was found (and removed), else 0. + * + * @remark Any held indices to elems[] are unusable after this call returns 1. + */ +RD_EXPORT +int +rd_kafka_topic_partition_list_del (rd_kafka_topic_partition_list_t *rktparlist, + const char *topic, int32_t partition); + + +/** + * @brief Delete partition from list by elems[] index. + * + * @returns 1 if partition was found (and removed), else 0. + * + * @sa rd_kafka_topic_partition_list_del() + */ +RD_EXPORT +int +rd_kafka_topic_partition_list_del_by_idx ( + rd_kafka_topic_partition_list_t *rktparlist, + int idx); + + +/** + * @brief Make a copy of an existing list. + * + * @param src The existing list to copy. + * + * @returns A new list fully populated to be identical to \p src + */ +RD_EXPORT +rd_kafka_topic_partition_list_t * +rd_kafka_topic_partition_list_copy (const rd_kafka_topic_partition_list_t *src); + + + + +/** + * @brief Set offset to \p offset for \p topic and \p partition + * + * @returns RD_KAFKA_RESP_ERR_NO_ERROR on success or + * RD_KAFKA_RESP_ERR__UNKNOWN_PARTITION if \p partition was not found + * in the list. + */ +RD_EXPORT +rd_kafka_resp_err_t rd_kafka_topic_partition_list_set_offset ( + rd_kafka_topic_partition_list_t *rktparlist, + const char *topic, int32_t partition, int64_t offset); + + + +/** + * @brief Find element by \p topic and \p partition. + * + * @returns a pointer to the first matching element, or NULL if not found. + */ +RD_EXPORT +rd_kafka_topic_partition_t * +rd_kafka_topic_partition_list_find (rd_kafka_topic_partition_list_t *rktparlist, + const char *topic, int32_t partition); + + +/** + * @brief Sort list using comparator \p cmp. + * + * If \p cmp is NULL the default comparator will be used that + * sorts by ascending topic name and partition. + * + */ +RD_EXPORT void +rd_kafka_topic_partition_list_sort (rd_kafka_topic_partition_list_t *rktparlist, + int (*cmp) (const void *a, const void *b, + void *opaque), + void *opaque); + + +/**@}*/ + + + +/** + * @name Var-arg tag types + * @{ + * + */ + +/** + * @enum rd_kafka_vtype_t + * + * @brief Var-arg tag types + * + * @sa rd_kafka_producev() + */ +typedef enum rd_kafka_vtype_t { + RD_KAFKA_VTYPE_END, /**< va-arg sentinel */ + RD_KAFKA_VTYPE_TOPIC, /**< (const char *) Topic name */ + RD_KAFKA_VTYPE_RKT, /**< (rd_kafka_topic_t *) Topic handle */ + RD_KAFKA_VTYPE_PARTITION, /**< (int32_t) Partition */ + RD_KAFKA_VTYPE_VALUE, /**< (void *, size_t) Message value (payload)*/ + RD_KAFKA_VTYPE_KEY, /**< (void *, size_t) Message key */ + RD_KAFKA_VTYPE_OPAQUE, /**< (void *) Application opaque */ + RD_KAFKA_VTYPE_MSGFLAGS, /**< (int) RD_KAFKA_MSG_F_.. flags */ + RD_KAFKA_VTYPE_TIMESTAMP, /**< (int64_t) Milliseconds since epoch UTC */ + RD_KAFKA_VTYPE_HEADER, /**< (const char *, const void *, ssize_t) + * Message Header */ + RD_KAFKA_VTYPE_HEADERS, /**< (rd_kafka_headers_t *) Headers list */ +} rd_kafka_vtype_t; + + +/** + * @brief Convenience macros for rd_kafka_vtype_t that takes the + * correct arguments for each vtype. + */ + +/*! + * va-arg end sentinel used to terminate the variable argument list + */ +#define RD_KAFKA_V_END RD_KAFKA_VTYPE_END + +/*! + * Topic name (const char *) + */ +#define RD_KAFKA_V_TOPIC(topic) \ + _LRK_TYPECHECK(RD_KAFKA_VTYPE_TOPIC, const char *, topic), \ + (const char *)topic +/*! + * Topic object (rd_kafka_topic_t *) + */ +#define RD_KAFKA_V_RKT(rkt) \ + _LRK_TYPECHECK(RD_KAFKA_VTYPE_RKT, rd_kafka_topic_t *, rkt), \ + (rd_kafka_topic_t *)rkt +/*! + * Partition (int32_t) + */ +#define RD_KAFKA_V_PARTITION(partition) \ + _LRK_TYPECHECK(RD_KAFKA_VTYPE_PARTITION, int32_t, partition), \ + (int32_t)partition +/*! + * Message value/payload pointer and length (void *, size_t) + */ +#define RD_KAFKA_V_VALUE(VALUE,LEN) \ + _LRK_TYPECHECK2(RD_KAFKA_VTYPE_VALUE, void *, VALUE, size_t, LEN), \ + (void *)VALUE, (size_t)LEN +/*! + * Message key pointer and length (const void *, size_t) + */ +#define RD_KAFKA_V_KEY(KEY,LEN) \ + _LRK_TYPECHECK2(RD_KAFKA_VTYPE_KEY, const void *, KEY, size_t, LEN), \ + (void *)KEY, (size_t)LEN +/*! + * Message opaque pointer (void *) + * Same as \c produce(.., msg_opaque), and \c rkmessage->_private . + */ +#define RD_KAFKA_V_OPAQUE(opaque) \ + _LRK_TYPECHECK(RD_KAFKA_VTYPE_OPAQUE, void *, opaque), \ + (void *)opaque +/*! + * Message flags (int) + * @sa RD_KAFKA_MSG_F_COPY, et.al. + */ +#define RD_KAFKA_V_MSGFLAGS(msgflags) \ + _LRK_TYPECHECK(RD_KAFKA_VTYPE_MSGFLAGS, int, msgflags), \ + (int)msgflags +/*! + * Timestamp (int64_t) + */ +#define RD_KAFKA_V_TIMESTAMP(timestamp) \ + _LRK_TYPECHECK(RD_KAFKA_VTYPE_TIMESTAMP, int64_t, timestamp), \ + (int64_t)timestamp +/*! + * Add Message Header (const char *NAME, const void *VALUE, ssize_t LEN). + * @sa rd_kafka_header_add() + * @remark RD_KAFKA_V_HEADER() and RD_KAFKA_V_HEADERS() MUST NOT be mixed + * in the same call to producev(). + */ +#define RD_KAFKA_V_HEADER(NAME,VALUE,LEN) \ + _LRK_TYPECHECK3(RD_KAFKA_VTYPE_HEADER, const char *, NAME, \ + const void *, VALUE, ssize_t, LEN), \ + (const char *)NAME, (const void *)VALUE, (ssize_t)LEN + +/*! + * Message Headers list (rd_kafka_headers_t *). + * The message object will assume ownership of the headers (unless producev() + * fails). + * Any existing headers will be replaced. + * @sa rd_kafka_message_set_headers() + * @remark RD_KAFKA_V_HEADER() and RD_KAFKA_V_HEADERS() MUST NOT be mixed + * in the same call to producev(). + */ +#define RD_KAFKA_V_HEADERS(HDRS) \ + _LRK_TYPECHECK(RD_KAFKA_VTYPE_HEADERS, rd_kafka_headers_t *, HDRS), \ + (rd_kafka_headers_t *)HDRS + + +/**@}*/ + + +/** + * @name Message headers + * @{ + * + * @brief Message headers consist of a list of (string key, binary value) pairs. + * Duplicate keys are supported and the order in which keys were + * added are retained. + * + * Header values are considered binary and may have three types of + * value: + * - proper value with size > 0 and a valid pointer + * - empty value with size = 0 and any non-NULL pointer + * - null value with size = 0 and a NULL pointer + * + * Headers require Apache Kafka broker version v0.11.0.0 or later. + * + * Header operations are O(n). + */ + +typedef struct rd_kafka_headers_s rd_kafka_headers_t; + +/** + * @brief Create a new headers list. + * + * @param initial_count Preallocate space for this number of headers. + * Any number of headers may be added, updated and + * removed regardless of the initial count. + */ +RD_EXPORT rd_kafka_headers_t *rd_kafka_headers_new (size_t initial_count); + +/** + * @brief Destroy the headers list. The object and any returned value pointers + * are not usable after this call. + */ +RD_EXPORT void rd_kafka_headers_destroy (rd_kafka_headers_t *hdrs); + +/** + * @brief Make a copy of headers list \p src. + */ +RD_EXPORT rd_kafka_headers_t * +rd_kafka_headers_copy (const rd_kafka_headers_t *src); + +/** + * @brief Add header with name \p name and value \p val (copied) of size + * \p size (not including null-terminator). + * + * @param name Header name. + * @param name_size Header name size (not including the null-terminator). + * If -1 the \p name length is automatically acquired using + * strlen(). + * @param value Pointer to header value, or NULL (set size to 0 or -1). + * @param value_size Size of header value. If -1 the \p value is assumed to be a + * null-terminated string and the length is automatically + * acquired using strlen(). + * + * @returns RD_KAFKA_RESP_ERR__READ_ONLY if the headers are read-only, + * else RD_KAFKA_RESP_ERR_NO_ERROR. + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_header_add (rd_kafka_headers_t *hdrs, + const char *name, ssize_t name_size, + const void *value, ssize_t value_size); + +/** + * @brief Remove all headers for the given key (if any). + * + * @returns RD_KAFKA_RESP_ERR__READ_ONLY if the headers are read-only, + * RD_KAFKA_RESP_ERR__NOENT if no matching headers were found, + * else RD_KAFKA_RESP_ERR_NO_ERROR if headers were removed. + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_header_remove (rd_kafka_headers_t *hdrs, const char *name); + + +/** + * @brief Find last header in list \p hdrs matching \p name. + * + * @param name Header to find (last match). + * @param valuep (out) Set to a (null-terminated) const pointer to the value + * (may be NULL). + * @param sizep (out) Set to the value's size (not including null-terminator). + * + * @returns RD_KAFKA_RESP_ERR_NO_ERROR if an entry was found, else + * RD_KAFKA_RESP_ERR__NOENT. + * + * @remark The returned pointer in \p valuep includes a trailing null-terminator + * that is not accounted for in \p sizep. + * @remark The returned pointer is only valid as long as the headers list and + * the header item is valid. + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_header_get_last (const rd_kafka_headers_t *hdrs, + const char *name, const void **valuep, size_t *sizep); + +/** + * @brief Iterator for headers matching \p name. + * + * Same semantics as rd_kafka_header_get_last() + * + * @param hdrs Headers to iterate. + * @param idx Iterator index, start at 0 and increment by one for each call + * as long as RD_KAFKA_RESP_ERR_NO_ERROR is returned. + * @param name Header name to match. + * @param valuep (out) Set to a (null-terminated) const pointer to the value + * (may be NULL). + * @param sizep (out) Set to the value's size (not including null-terminator). + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_header_get (const rd_kafka_headers_t *hdrs, size_t idx, + const char *name, const void **valuep, size_t *sizep); + + +/** + * @brief Iterator for all headers. + * + * Same semantics as rd_kafka_header_get() + * + * @sa rd_kafka_header_get() + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_header_get_all (const rd_kafka_headers_t *hdrs, size_t idx, + const char **namep, + const void **valuep, size_t *sizep); + + + +/**@}*/ + + + +/** + * @name Kafka messages + * @{ + * + */ + + + +// FIXME: This doesn't show up in docs for some reason +// "Compound rd_kafka_message_t is not documented." + +/** + * @brief A Kafka message as returned by the \c rd_kafka_consume*() family + * of functions as well as provided to the Producer \c dr_msg_cb(). + * + * For the consumer this object has two purposes: + * - provide the application with a consumed message. (\c err == 0) + * - report per-topic+partition consumer errors (\c err != 0) + * + * The application must check \c err to decide what action to take. + * + * When the application is finished with a message it must call + * rd_kafka_message_destroy() unless otherwise noted. + */ +typedef struct rd_kafka_message_s { + rd_kafka_resp_err_t err; /**< Non-zero for error signaling. */ + rd_kafka_topic_t *rkt; /**< Topic */ + int32_t partition; /**< Partition */ + void *payload; /**< Producer: original message payload. + * Consumer: Depends on the value of \c err : + * - \c err==0: Message payload. + * - \c err!=0: Error string */ + size_t len; /**< Depends on the value of \c err : + * - \c err==0: Message payload length + * - \c err!=0: Error string length */ + void *key; /**< Depends on the value of \c err : + * - \c err==0: Optional message key */ + size_t key_len; /**< Depends on the value of \c err : + * - \c err==0: Optional message key length*/ + int64_t offset; /**< Consume: + * - Message offset (or offset for error + * if \c err!=0 if applicable). + * - dr_msg_cb: + * Message offset assigned by broker. + * If \c produce.offset.report is set then + * each message will have this field set, + * otherwise only the last message in + * each produced internal batch will + * have this field set, otherwise 0. */ + void *_private; /**< Consume: + * - rdkafka private pointer: DO NOT MODIFY + * - dr_msg_cb: + * msg_opaque from produce() call */ +} rd_kafka_message_t; + + +/** + * @brief Frees resources for \p rkmessage and hands ownership back to rdkafka. + */ +RD_EXPORT +void rd_kafka_message_destroy(rd_kafka_message_t *rkmessage); + + + + +/** + * @brief Returns the error string for an errored rd_kafka_message_t or NULL if + * there was no error. + * + * @remark This function MUST NOT be used with the producer. + */ +static RD_INLINE const char * +RD_UNUSED +rd_kafka_message_errstr(const rd_kafka_message_t *rkmessage) { + if (!rkmessage->err) + return NULL; + + if (rkmessage->payload) + return (const char *)rkmessage->payload; + + return rd_kafka_err2str(rkmessage->err); +} + + + +/** + * @brief Returns the message timestamp for a consumed message. + * + * The timestamp is the number of milliseconds since the epoch (UTC). + * + * \p tstype (if not NULL) is updated to indicate the type of timestamp. + * + * @returns message timestamp, or -1 if not available. + * + * @remark Message timestamps require broker version 0.10.0 or later. + */ +RD_EXPORT +int64_t rd_kafka_message_timestamp (const rd_kafka_message_t *rkmessage, + rd_kafka_timestamp_type_t *tstype); + + + +/** + * @brief Returns the latency for a produced message measured from + * the produce() call. + * + * @returns the latency in microseconds, or -1 if not available. + */ +RD_EXPORT +int64_t rd_kafka_message_latency (const rd_kafka_message_t *rkmessage); + + +/** + * @brief Get the message header list. + * + * The returned pointer in \p *hdrsp is associated with the \p rkmessage and + * must not be used after destruction of the message object or the header + * list is replaced with rd_kafka_message_set_headers(). + * + * @returns RD_KAFKA_RESP_ERR_NO_ERROR if headers were returned, + * RD_KAFKA_RESP_ERR__NOENT if the message has no headers, + * or another error code if the headers could not be parsed. + * + * @remark Headers require broker version 0.11.0.0 or later. + * + * @remark As an optimization the raw protocol headers are parsed on + * the first call to this function. + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_message_headers (const rd_kafka_message_t *rkmessage, + rd_kafka_headers_t **hdrsp); + + +/** + * @brief Replace the message's current headers with a new list. + * + * @param hdrs New header list. The message object assumes ownership of + * the list, the list will be destroyed automatically with + * the message object. + * The new headers list may be updated until the message object + * is passed or returned to librdkafka. + * + * @remark The existing headers object, if any, will be destroyed. + */ +RD_EXPORT +void rd_kafka_message_set_headers (rd_kafka_message_t *rkmessage, + rd_kafka_headers_t *hdrs); + + +/** + * @brief Returns the number of header key/value pairs + * + * @param hdrs Headers to count + */ +RD_EXPORT size_t rd_kafka_header_cnt (const rd_kafka_headers_t *hdrs); + + +/**@}*/ + + +/** + * @name Configuration interface + * @{ + * + * @brief Main/global configuration property interface + * + */ + +/** + * @enum rd_kafka_conf_res_t + * @brief Configuration result type + */ +typedef enum { + RD_KAFKA_CONF_UNKNOWN = -2, /**< Unknown configuration name. */ + RD_KAFKA_CONF_INVALID = -1, /**< Invalid configuration value. */ + RD_KAFKA_CONF_OK = 0 /**< Configuration okay */ +} rd_kafka_conf_res_t; + + +/** + * @brief Create configuration object. + * + * When providing your own configuration to the \c rd_kafka_*_new_*() calls + * the rd_kafka_conf_t objects needs to be created with this function + * which will set up the defaults. + * I.e.: + * @code + * rd_kafka_conf_t *myconf; + * rd_kafka_conf_res_t res; + * + * myconf = rd_kafka_conf_new(); + * res = rd_kafka_conf_set(myconf, "socket.timeout.ms", "600", + * errstr, sizeof(errstr)); + * if (res != RD_KAFKA_CONF_OK) + * die("%s\n", errstr); + * + * rk = rd_kafka_new(..., myconf); + * @endcode + * + * Please see CONFIGURATION.md for the default settings or use + * rd_kafka_conf_properties_show() to provide the information at runtime. + * + * The properties are identical to the Apache Kafka configuration properties + * whenever possible. + * + * @returns A new rd_kafka_conf_t object with defaults set. + * + * @sa rd_kafka_conf_set(), rd_kafka_conf_destroy() + */ +RD_EXPORT +rd_kafka_conf_t *rd_kafka_conf_new(void); + + +/** + * @brief Destroys a conf object. + */ +RD_EXPORT +void rd_kafka_conf_destroy(rd_kafka_conf_t *conf); + + +/** + * @brief Creates a copy/duplicate of configuration object \p conf + * + * @remark Interceptors are NOT copied to the new configuration object. + * @sa rd_kafka_interceptor_f_on_conf_dup + */ +RD_EXPORT +rd_kafka_conf_t *rd_kafka_conf_dup(const rd_kafka_conf_t *conf); + + +/** + * @brief Same as rd_kafka_conf_dup() but with an array of property name + * prefixes to filter out (ignore) when copying. + */ +RD_EXPORT +rd_kafka_conf_t *rd_kafka_conf_dup_filter (const rd_kafka_conf_t *conf, + size_t filter_cnt, + const char **filter); + + + +/** + * @brief Sets a configuration property. + * + * \p conf must have been previously created with rd_kafka_conf_new(). + * + * Fallthrough: + * Topic-level configuration properties may be set using this interface + * in which case they are applied on the \c default_topic_conf. + * If no \c default_topic_conf has been set one will be created. + * Any sub-sequent rd_kafka_conf_set_default_topic_conf() calls will + * replace the current default topic configuration. + * + * @returns \c rd_kafka_conf_res_t to indicate success or failure. + * In case of failure \p errstr is updated to contain a human readable + * error string. + */ +RD_EXPORT +rd_kafka_conf_res_t rd_kafka_conf_set(rd_kafka_conf_t *conf, + const char *name, + const char *value, + char *errstr, size_t errstr_size); + + +/** + * @brief Enable event sourcing. + * \p events is a bitmask of \c RD_KAFKA_EVENT_* of events to enable + * for consumption by `rd_kafka_queue_poll()`. + */ +RD_EXPORT +void rd_kafka_conf_set_events(rd_kafka_conf_t *conf, int events); + + +/** + @deprecated See rd_kafka_conf_set_dr_msg_cb() +*/ +RD_EXPORT +void rd_kafka_conf_set_dr_cb(rd_kafka_conf_t *conf, + void (*dr_cb) (rd_kafka_t *rk, + void *payload, size_t len, + rd_kafka_resp_err_t err, + void *opaque, void *msg_opaque)); + +/** + * @brief \b Producer: Set delivery report callback in provided \p conf object. + * + * The delivery report callback will be called once for each message + * accepted by rd_kafka_produce() (et.al) with \p err set to indicate + * the result of the produce request. + * + * The callback is called when a message is succesfully produced or + * if librdkafka encountered a permanent failure, or the retry counter for + * temporary errors has been exhausted. + * + * An application must call rd_kafka_poll() at regular intervals to + * serve queued delivery report callbacks. + */ +RD_EXPORT +void rd_kafka_conf_set_dr_msg_cb(rd_kafka_conf_t *conf, + void (*dr_msg_cb) (rd_kafka_t *rk, + const rd_kafka_message_t * + rkmessage, + void *opaque)); + + +/** + * @brief \b Consumer: Set consume callback for use with rd_kafka_consumer_poll() + * + */ +RD_EXPORT +void rd_kafka_conf_set_consume_cb (rd_kafka_conf_t *conf, + void (*consume_cb) (rd_kafka_message_t * + rkmessage, + void *opaque)); + +/** + * @brief \b Consumer: Set rebalance callback for use with + * coordinated consumer group balancing. + * + * The \p err field is set to either RD_KAFKA_RESP_ERR__ASSIGN_PARTITIONS + * or RD_KAFKA_RESP_ERR__REVOKE_PARTITIONS and 'partitions' + * contains the full partition set that was either assigned or revoked. + * + * Registering a \p rebalance_cb turns off librdkafka's automatic + * partition assignment/revocation and instead delegates that responsibility + * to the application's \p rebalance_cb. + * + * The rebalance callback is responsible for updating librdkafka's + * assignment set based on the two events: RD_KAFKA_RESP_ERR__ASSIGN_PARTITIONS + * and RD_KAFKA_RESP_ERR__REVOKE_PARTITIONS but should also be able to handle + * arbitrary rebalancing failures where \p err is neither of those. + * @remark In this latter case (arbitrary error), the application must + * call rd_kafka_assign(rk, NULL) to synchronize state. + * + * Without a rebalance callback this is done automatically by librdkafka + * but registering a rebalance callback gives the application flexibility + * in performing other operations along with the assinging/revocation, + * such as fetching offsets from an alternate location (on assign) + * or manually committing offsets (on revoke). + * + * @remark The \p partitions list is destroyed by librdkafka on return + * return from the rebalance_cb and must not be freed or + * saved by the application. + * + * The following example shows the application's responsibilities: + * @code + * static void rebalance_cb (rd_kafka_t *rk, rd_kafka_resp_err_t err, + * rd_kafka_topic_partition_list_t *partitions, + * void *opaque) { + * + * switch (err) + * { + * case RD_KAFKA_RESP_ERR__ASSIGN_PARTITIONS: + * // application may load offets from arbitrary external + * // storage here and update \p partitions + * + * rd_kafka_assign(rk, partitions); + * break; + * + * case RD_KAFKA_RESP_ERR__REVOKE_PARTITIONS: + * if (manual_commits) // Optional explicit manual commit + * rd_kafka_commit(rk, partitions, 0); // sync commit + * + * rd_kafka_assign(rk, NULL); + * break; + * + * default: + * handle_unlikely_error(err); + * rd_kafka_assign(rk, NULL); // sync state + * break; + * } + * } + * @endcode + */ +RD_EXPORT +void rd_kafka_conf_set_rebalance_cb ( + rd_kafka_conf_t *conf, + void (*rebalance_cb) (rd_kafka_t *rk, + rd_kafka_resp_err_t err, + rd_kafka_topic_partition_list_t *partitions, + void *opaque)); + + + +/** + * @brief \b Consumer: Set offset commit callback for use with consumer groups. + * + * The results of automatic or manual offset commits will be scheduled + * for this callback and is served by rd_kafka_consumer_poll(). + * + * If no partitions had valid offsets to commit this callback will be called + * with \p err == RD_KAFKA_RESP_ERR__NO_OFFSET which is not to be considered + * an error. + * + * The \p offsets list contains per-partition information: + * - \c offset: committed offset (attempted) + * - \c err: commit error + */ +RD_EXPORT +void rd_kafka_conf_set_offset_commit_cb ( + rd_kafka_conf_t *conf, + void (*offset_commit_cb) (rd_kafka_t *rk, + rd_kafka_resp_err_t err, + rd_kafka_topic_partition_list_t *offsets, + void *opaque)); + + +/** + * @brief Set error callback in provided conf object. + * + * The error callback is used by librdkafka to signal critical errors + * back to the application. + * + * If no \p error_cb is registered then the errors will be logged instead. + */ +RD_EXPORT +void rd_kafka_conf_set_error_cb(rd_kafka_conf_t *conf, + void (*error_cb) (rd_kafka_t *rk, int err, + const char *reason, + void *opaque)); + +/** + * @brief Set throttle callback. + * + * The throttle callback is used to forward broker throttle times to the + * application for Produce and Fetch (consume) requests. + * + * Callbacks are triggered whenever a non-zero throttle time is returned by + * the broker, or when the throttle time drops back to zero. + * + * An application must call rd_kafka_poll() or rd_kafka_consumer_poll() at + * regular intervals to serve queued callbacks. + * + * @remark Requires broker version 0.9.0 or later. + */ +RD_EXPORT +void rd_kafka_conf_set_throttle_cb (rd_kafka_conf_t *conf, + void (*throttle_cb) ( + rd_kafka_t *rk, + const char *broker_name, + int32_t broker_id, + int throttle_time_ms, + void *opaque)); + + +/** + * @brief Set logger callback. + * + * The default is to print to stderr, but a syslog logger is also available, + * see rd_kafka_log_print and rd_kafka_log_syslog for the builtin alternatives. + * Alternatively the application may provide its own logger callback. + * Or pass \p func as NULL to disable logging. + * + * This is the configuration alternative to the deprecated rd_kafka_set_logger() + * + * @remark The log_cb will be called spontaneously from librdkafka's internal + * threads unless logs have been forwarded to a poll queue through + * \c rd_kafka_set_log_queue(). + * An application MUST NOT call any librdkafka APIs or do any prolonged + * work in a non-forwarded \c log_cb. + */ +RD_EXPORT +void rd_kafka_conf_set_log_cb(rd_kafka_conf_t *conf, + void (*log_cb) (const rd_kafka_t *rk, int level, + const char *fac, const char *buf)); + + +/** + * @brief Set statistics callback in provided conf object. + * + * The statistics callback is triggered from rd_kafka_poll() every + * \c statistics.interval.ms (needs to be configured separately). + * Function arguments: + * - \p rk - Kafka handle + * - \p json - String containing the statistics data in JSON format + * - \p json_len - Length of \p json string. + * - \p opaque - Application-provided opaque. + * + * If the application wishes to hold on to the \p json pointer and free + * it at a later time it must return 1 from the \p stats_cb. + * If the application returns 0 from the \p stats_cb then librdkafka + * will immediately free the \p json pointer. + */ +RD_EXPORT +void rd_kafka_conf_set_stats_cb(rd_kafka_conf_t *conf, + int (*stats_cb) (rd_kafka_t *rk, + char *json, + size_t json_len, + void *opaque)); + + + +/** + * @brief Set socket callback. + * + * The socket callback is responsible for opening a socket + * according to the supplied \p domain, \p type and \p protocol. + * The socket shall be created with \c CLOEXEC set in a racefree fashion, if + * possible. + * + * Default: + * - on linux: racefree CLOEXEC + * - others : non-racefree CLOEXEC + * + * @remark The callback will be called from an internal librdkafka thread. + */ +RD_EXPORT +void rd_kafka_conf_set_socket_cb(rd_kafka_conf_t *conf, + int (*socket_cb) (int domain, int type, + int protocol, + void *opaque)); + + + +/** + * @brief Set connect callback. + * + * The connect callback is responsible for connecting socket \p sockfd + * to peer address \p addr. + * The \p id field contains the broker identifier. + * + * \p connect_cb shall return 0 on success (socket connected) or an error + * number (errno) on error. + * + * @remark The callback will be called from an internal librdkafka thread. + */ +RD_EXPORT void +rd_kafka_conf_set_connect_cb (rd_kafka_conf_t *conf, + int (*connect_cb) (int sockfd, + const struct sockaddr *addr, + int addrlen, + const char *id, + void *opaque)); + +/** + * @brief Set close socket callback. + * + * Close a socket (optionally opened with socket_cb()). + * + * @remark The callback will be called from an internal librdkafka thread. + */ +RD_EXPORT void +rd_kafka_conf_set_closesocket_cb (rd_kafka_conf_t *conf, + int (*closesocket_cb) (int sockfd, + void *opaque)); + + + +#ifndef _MSC_VER +/** + * @brief Set open callback. + * + * The open callback is responsible for opening the file specified by + * pathname, flags and mode. + * The file shall be opened with \c CLOEXEC set in a racefree fashion, if + * possible. + * + * Default: + * - on linux: racefree CLOEXEC + * - others : non-racefree CLOEXEC + * + * @remark The callback will be called from an internal librdkafka thread. + */ +RD_EXPORT +void rd_kafka_conf_set_open_cb (rd_kafka_conf_t *conf, + int (*open_cb) (const char *pathname, + int flags, mode_t mode, + void *opaque)); +#endif + +/** + * @brief Sets the application's opaque pointer that will be passed to callbacks + */ +RD_EXPORT +void rd_kafka_conf_set_opaque(rd_kafka_conf_t *conf, void *opaque); + +/** + * @brief Retrieves the opaque pointer previously set with rd_kafka_conf_set_opaque() + */ +RD_EXPORT +void *rd_kafka_opaque(const rd_kafka_t *rk); + + + +/** + * Sets the default topic configuration to use for automatically + * subscribed topics (e.g., through pattern-matched topics). + * The topic config object is not usable after this call. + */ +RD_EXPORT +void rd_kafka_conf_set_default_topic_conf (rd_kafka_conf_t *conf, + rd_kafka_topic_conf_t *tconf); + + + +/** + * @brief Retrieve configuration value for property \p name. + * + * If \p dest is non-NULL the value will be written to \p dest with at + * most \p dest_size. + * + * \p *dest_size is updated to the full length of the value, thus if + * \p *dest_size initially is smaller than the full length the application + * may reallocate \p dest to fit the returned \p *dest_size and try again. + * + * If \p dest is NULL only the full length of the value is returned. + * + * Fallthrough: + * Topic-level configuration properties from the \c default_topic_conf + * may be retrieved using this interface. + * + * @returns \p RD_KAFKA_CONF_OK if the property name matched, else + * \p RD_KAFKA_CONF_UNKNOWN. + */ +RD_EXPORT +rd_kafka_conf_res_t rd_kafka_conf_get (const rd_kafka_conf_t *conf, + const char *name, + char *dest, size_t *dest_size); + + +/** + * @brief Retrieve topic configuration value for property \p name. + * + * @sa rd_kafka_conf_get() + */ +RD_EXPORT +rd_kafka_conf_res_t rd_kafka_topic_conf_get (const rd_kafka_topic_conf_t *conf, + const char *name, + char *dest, size_t *dest_size); + + +/** + * @brief Dump the configuration properties and values of \p conf to an array + * with \"key\", \"value\" pairs. + * + * The number of entries in the array is returned in \p *cntp. + * + * The dump must be freed with `rd_kafka_conf_dump_free()`. + */ +RD_EXPORT +const char **rd_kafka_conf_dump(rd_kafka_conf_t *conf, size_t *cntp); + + +/** + * @brief Dump the topic configuration properties and values of \p conf + * to an array with \"key\", \"value\" pairs. + * + * The number of entries in the array is returned in \p *cntp. + * + * The dump must be freed with `rd_kafka_conf_dump_free()`. + */ +RD_EXPORT +const char **rd_kafka_topic_conf_dump(rd_kafka_topic_conf_t *conf, + size_t *cntp); + +/** + * @brief Frees a configuration dump returned from `rd_kafka_conf_dump()` or + * `rd_kafka_topic_conf_dump(). + */ +RD_EXPORT +void rd_kafka_conf_dump_free(const char **arr, size_t cnt); + +/** + * @brief Prints a table to \p fp of all supported configuration properties, + * their default values as well as a description. + */ +RD_EXPORT +void rd_kafka_conf_properties_show(FILE *fp); + +/**@}*/ + + +/** + * @name Topic configuration + * @{ + * + * @brief Topic configuration property interface + * + */ + + +/** + * @brief Create topic configuration object + * + * @sa Same semantics as for rd_kafka_conf_new(). + */ +RD_EXPORT +rd_kafka_topic_conf_t *rd_kafka_topic_conf_new(void); + + +/** + * @brief Creates a copy/duplicate of topic configuration object \p conf. + */ +RD_EXPORT +rd_kafka_topic_conf_t *rd_kafka_topic_conf_dup(const rd_kafka_topic_conf_t + *conf); + +/** + * @brief Creates a copy/duplicate of \p rk 's default topic configuration + * object. + */ +RD_EXPORT +rd_kafka_topic_conf_t *rd_kafka_default_topic_conf_dup (rd_kafka_t *rk); + + +/** + * @brief Destroys a topic conf object. + */ +RD_EXPORT +void rd_kafka_topic_conf_destroy(rd_kafka_topic_conf_t *topic_conf); + + +/** + * @brief Sets a single rd_kafka_topic_conf_t value by property name. + * + * \p topic_conf should have been previously set up + * with `rd_kafka_topic_conf_new()`. + * + * @returns rd_kafka_conf_res_t to indicate success or failure. + */ +RD_EXPORT +rd_kafka_conf_res_t rd_kafka_topic_conf_set(rd_kafka_topic_conf_t *conf, + const char *name, + const char *value, + char *errstr, size_t errstr_size); + +/** + * @brief Sets the application's opaque pointer that will be passed to all topic + * callbacks as the \c rkt_opaque argument. + */ +RD_EXPORT +void rd_kafka_topic_conf_set_opaque(rd_kafka_topic_conf_t *conf, void *opaque); + + +/** + * @brief \b Producer: Set partitioner callback in provided topic conf object. + * + * The partitioner may be called in any thread at any time, + * it may be called multiple times for the same message/key. + * + * Partitioner function constraints: + * - MUST NOT call any rd_kafka_*() functions except: + * rd_kafka_topic_partition_available() + * - MUST NOT block or execute for prolonged periods of time. + * - MUST return a value between 0 and partition_cnt-1, or the + * special \c RD_KAFKA_PARTITION_UA value if partitioning + * could not be performed. + */ +RD_EXPORT +void +rd_kafka_topic_conf_set_partitioner_cb (rd_kafka_topic_conf_t *topic_conf, + int32_t (*partitioner) ( + const rd_kafka_topic_t *rkt, + const void *keydata, + size_t keylen, + int32_t partition_cnt, + void *rkt_opaque, + void *msg_opaque)); + + +/** + * @brief \b Producer: Set message queueing order comparator callback. + * + * The callback may be called in any thread at any time, + * it may be called multiple times for the same message. + * + * Ordering comparator function constraints: + * - MUST be stable sort (same input gives same output). + * - MUST NOT call any rd_kafka_*() functions. + * - MUST NOT block or execute for prolonged periods of time. + * + * The comparator shall compare the two messages and return: + * - < 0 if message \p a should be inserted before message \p b. + * - >=0 if message \p a should be inserted after message \p b. + * + * @remark Insert sorting will be used to enqueue the message in the + * correct queue position, this comes at a cost of O(n). + * + * @remark If `queuing.strategy=fifo` new messages are enqueued to the + * tail of the queue regardless of msg_order_cmp, but retried messages + * are still affected by msg_order_cmp. + * + * @warning THIS IS AN EXPERIMENTAL API, SUBJECT TO CHANGE OR REMOVAL, + * DO NOT USE IN PRODUCTION. + */ +RD_EXPORT void +rd_kafka_topic_conf_set_msg_order_cmp (rd_kafka_topic_conf_t *topic_conf, + int (*msg_order_cmp) ( + const rd_kafka_message_t *a, + const rd_kafka_message_t *b)); + + +/** + * @brief Check if partition is available (has a leader broker). + * + * @returns 1 if the partition is available, else 0. + * + * @warning This function must only be called from inside a partitioner function + */ +RD_EXPORT +int rd_kafka_topic_partition_available(const rd_kafka_topic_t *rkt, + int32_t partition); + + +/******************************************************************* + * * + * Partitioners provided by rdkafka * + * * + *******************************************************************/ + +/** + * @brief Random partitioner. + * + * Will try not to return unavailable partitions. + * + * @returns a random partition between 0 and \p partition_cnt - 1. + * + */ +RD_EXPORT +int32_t rd_kafka_msg_partitioner_random(const rd_kafka_topic_t *rkt, + const void *key, size_t keylen, + int32_t partition_cnt, + void *opaque, void *msg_opaque); + +/** + * @brief Consistent partitioner. + * + * Uses consistent hashing to map identical keys onto identical partitions. + * + * @returns a \"random\" partition between 0 and \p partition_cnt - 1 based on + * the CRC value of the key + */ +RD_EXPORT +int32_t rd_kafka_msg_partitioner_consistent (const rd_kafka_topic_t *rkt, + const void *key, size_t keylen, + int32_t partition_cnt, + void *opaque, void *msg_opaque); + +/** + * @brief Consistent-Random partitioner. + * + * This is the default partitioner. + * Uses consistent hashing to map identical keys onto identical partitions, and + * messages without keys will be assigned via the random partitioner. + * + * @returns a \"random\" partition between 0 and \p partition_cnt - 1 based on + * the CRC value of the key (if provided) + */ +RD_EXPORT +int32_t rd_kafka_msg_partitioner_consistent_random (const rd_kafka_topic_t *rkt, + const void *key, size_t keylen, + int32_t partition_cnt, + void *opaque, void *msg_opaque); + + +/** + * @brief Murmur2 partitioner (Java compatible). + * + * Uses consistent hashing to map identical keys onto identical partitions + * using Java-compatible Murmur2 hashing. + * + * @returns a partition between 0 and \p partition_cnt - 1. + */ +RD_EXPORT +int32_t rd_kafka_msg_partitioner_murmur2 (const rd_kafka_topic_t *rkt, + const void *key, size_t keylen, + int32_t partition_cnt, + void *rkt_opaque, + void *msg_opaque); + +/** + * @brief Consistent-Random Murmur2 partitioner (Java compatible). + * + * Uses consistent hashing to map identical keys onto identical partitions + * using Java-compatible Murmur2 hashing. + * Messages without keys will be assigned via the random partitioner. + * + * @returns a partition between 0 and \p partition_cnt - 1. + */ +RD_EXPORT +int32_t rd_kafka_msg_partitioner_murmur2_random (const rd_kafka_topic_t *rkt, + const void *key, size_t keylen, + int32_t partition_cnt, + void *rkt_opaque, + void *msg_opaque); + + +/**@}*/ + + + +/** + * @name Main Kafka and Topic object handles + * @{ + * + * + */ + + + + +/** + * @brief Creates a new Kafka handle and starts its operation according to the + * specified \p type (\p RD_KAFKA_CONSUMER or \p RD_KAFKA_PRODUCER). + * + * \p conf is an optional struct created with `rd_kafka_conf_new()` that will + * be used instead of the default configuration. + * The \p conf object is freed by this function on success and must not be used + * or destroyed by the application sub-sequently. + * See `rd_kafka_conf_set()` et.al for more information. + * + * \p errstr must be a pointer to memory of at least size \p errstr_size where + * `rd_kafka_new()` may write a human readable error message in case the + * creation of a new handle fails. In which case the function returns NULL. + * + * @remark \b RD_KAFKA_CONSUMER: When a new \p RD_KAFKA_CONSUMER + * rd_kafka_t handle is created it may either operate in the + * legacy simple consumer mode using the rd_kafka_consume_start() + * interface, or the High-level KafkaConsumer API. + * @remark An application must only use one of these groups of APIs on a given + * rd_kafka_t RD_KAFKA_CONSUMER handle. + + * + * @returns The Kafka handle on success or NULL on error (see \p errstr) + * + * @sa To destroy the Kafka handle, use rd_kafka_destroy(). + */ +RD_EXPORT +rd_kafka_t *rd_kafka_new(rd_kafka_type_t type, rd_kafka_conf_t *conf, + char *errstr, size_t errstr_size); + + +/** + * @brief Destroy Kafka handle. + * + * @remark This is a blocking operation. + */ +RD_EXPORT +void rd_kafka_destroy(rd_kafka_t *rk); + + + +/** + * @brief Returns Kafka handle name. + */ +RD_EXPORT +const char *rd_kafka_name(const rd_kafka_t *rk); + + +/** + * @brief Returns Kafka handle type. + */ +RD_EXPORT +rd_kafka_type_t rd_kafka_type(const rd_kafka_t *rk); + + +/** + * @brief Returns this client's broker-assigned group member id + * + * @remark This currently requires the high-level KafkaConsumer + * + * @returns An allocated string containing the current broker-assigned group + * member id, or NULL if not available. + * The application must free the string with \p free() or + * rd_kafka_mem_free() + */ +RD_EXPORT +char *rd_kafka_memberid (const rd_kafka_t *rk); + + + +/** + * @brief Returns the ClusterId as reported in broker metadata. + * + * @param timeout_ms If there is no cached value from metadata retrieval + * then this specifies the maximum amount of time + * (in milliseconds) the call will block waiting + * for metadata to be retrieved. + * Use 0 for non-blocking calls. + + * @remark Requires broker version >=0.10.0 and api.version.request=true. + * + * @remark The application must free the returned pointer + * using rd_kafka_mem_free(). + * + * @returns a newly allocated string containing the ClusterId, or NULL + * if no ClusterId could be retrieved in the allotted timespan. + */ +RD_EXPORT +char *rd_kafka_clusterid (rd_kafka_t *rk, int timeout_ms); + + +/** + * @brief Creates a new topic handle for topic named \p topic. + * + * \p conf is an optional configuration for the topic created with + * `rd_kafka_topic_conf_new()` that will be used instead of the default + * topic configuration. + * The \p conf object is freed by this function and must not be used or + * destroyed by the application sub-sequently. + * See `rd_kafka_topic_conf_set()` et.al for more information. + * + * Topic handles are refcounted internally and calling rd_kafka_topic_new() + * again with the same topic name will return the previous topic handle + * without updating the original handle's configuration. + * Applications must eventually call rd_kafka_topic_destroy() for each + * succesfull call to rd_kafka_topic_new() to clear up resources. + * + * @returns the new topic handle or NULL on error (use rd_kafka_errno2err() + * to convert system \p errno to an rd_kafka_resp_err_t error code. + * + * @sa rd_kafka_topic_destroy() + */ +RD_EXPORT +rd_kafka_topic_t *rd_kafka_topic_new(rd_kafka_t *rk, const char *topic, + rd_kafka_topic_conf_t *conf); + + + +/** + * @brief Loose application's topic handle refcount as previously created + * with `rd_kafka_topic_new()`. + * + * @remark Since topic objects are refcounted (both internally and for the app) + * the topic object might not actually be destroyed by this call, + * but the application must consider the object destroyed. + */ +RD_EXPORT +void rd_kafka_topic_destroy(rd_kafka_topic_t *rkt); + + +/** + * @brief Returns the topic name. + */ +RD_EXPORT +const char *rd_kafka_topic_name(const rd_kafka_topic_t *rkt); + + +/** + * @brief Get the \p rkt_opaque pointer that was set in the topic configuration. + */ +RD_EXPORT +void *rd_kafka_topic_opaque (const rd_kafka_topic_t *rkt); + + +/** + * @brief Unassigned partition. + * + * The unassigned partition is used by the producer API for messages + * that should be partitioned using the configured or default partitioner. + */ +#define RD_KAFKA_PARTITION_UA ((int32_t)-1) + + +/** + * @brief Polls the provided kafka handle for events. + * + * Events will cause application provided callbacks to be called. + * + * The \p timeout_ms argument specifies the maximum amount of time + * (in milliseconds) that the call will block waiting for events. + * For non-blocking calls, provide 0 as \p timeout_ms. + * To wait indefinately for an event, provide -1. + * + * @remark An application should make sure to call poll() at regular + * intervals to serve any queued callbacks waiting to be called. + * + * Events: + * - delivery report callbacks (if dr_cb/dr_msg_cb is configured) [producer] + * - error callbacks (rd_kafka_conf_set_error_cb()) [all] + * - stats callbacks (rd_kafka_conf_set_stats_cb()) [all] + * - throttle callbacks (rd_kafka_conf_set_throttle_cb()) [all] + * + * @returns the number of events served. + */ +RD_EXPORT +int rd_kafka_poll(rd_kafka_t *rk, int timeout_ms); + + +/** + * @brief Cancels the current callback dispatcher (rd_kafka_poll(), + * rd_kafka_consume_callback(), etc). + * + * A callback may use this to force an immediate return to the calling + * code (caller of e.g. rd_kafka_poll()) without processing any further + * events. + * + * @remark This function MUST ONLY be called from within a librdkafka callback. + */ +RD_EXPORT +void rd_kafka_yield (rd_kafka_t *rk); + + + + +/** + * @brief Pause producing or consumption for the provided list of partitions. + * + * Success or error is returned per-partition \p err in the \p partitions list. + * + * @returns RD_KAFKA_RESP_ERR_NO_ERROR + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_pause_partitions (rd_kafka_t *rk, + rd_kafka_topic_partition_list_t *partitions); + + + +/** + * @brief Resume producing consumption for the provided list of partitions. + * + * Success or error is returned per-partition \p err in the \p partitions list. + * + * @returns RD_KAFKA_RESP_ERR_NO_ERROR + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_resume_partitions (rd_kafka_t *rk, + rd_kafka_topic_partition_list_t *partitions); + + + + +/** + * @brief Query broker for low (oldest/beginning) and high (newest/end) offsets + * for partition. + * + * Offsets are returned in \p *low and \p *high respectively. + * + * @returns RD_KAFKA_RESP_ERR_NO_ERROR on success or an error code on failure. + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_query_watermark_offsets (rd_kafka_t *rk, + const char *topic, int32_t partition, + int64_t *low, int64_t *high, int timeout_ms); + + +/** + * @brief Get last known low (oldest/beginning) and high (newest/end) offsets + * for partition. + * + * The low offset is updated periodically (if statistics.interval.ms is set) + * while the high offset is updated on each fetched message set from the broker. + * + * If there is no cached offset (either low or high, or both) then + * RD_KAFKA_OFFSET_INVALID will be returned for the respective offset. + * + * Offsets are returned in \p *low and \p *high respectively. + * + * @returns RD_KAFKA_RESP_ERR_NO_ERROR on success or an error code on failure. + * + * @remark Shall only be used with an active consumer instance. + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_get_watermark_offsets (rd_kafka_t *rk, + const char *topic, int32_t partition, + int64_t *low, int64_t *high); + + + +/** + * @brief Look up the offsets for the given partitions by timestamp. + * + * The returned offset for each partition is the earliest offset whose + * timestamp is greater than or equal to the given timestamp in the + * corresponding partition. + * + * The timestamps to query are represented as \c offset in \p offsets + * on input, and \c offset will contain the offset on output. + * + * The function will block for at most \p timeout_ms milliseconds. + * + * @remark Duplicate Topic+Partitions are not supported. + * @remark Per-partition errors may be returned in \c rd_kafka_topic_partition_t.err + * + * @returns RD_KAFKA_RESP_ERR_NO_ERROR if offsets were be queried (do note + * that per-partition errors might be set), + * RD_KAFKA_RESP_ERR__TIMED_OUT if not all offsets could be fetched + * within \p timeout_ms, + * RD_KAFKA_RESP_ERR__INVALID_ARG if the \p offsets list is empty, + * RD_KAFKA_RESP_ERR__UNKNOWN_PARTITION if all partitions are unknown, + * RD_KAFKA_RESP_ERR_LEADER_NOT_AVAILABLE if unable to query leaders + * for the given partitions. + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_offsets_for_times (rd_kafka_t *rk, + rd_kafka_topic_partition_list_t *offsets, + int timeout_ms); + + +/** + * @brief Free pointer returned by librdkafka + * + * This is typically an abstraction for the free(3) call and makes sure + * the application can use the same memory allocator as librdkafka for + * freeing pointers returned by librdkafka. + * + * In standard setups it is usually not necessary to use this interface + * rather than the free(3) functione. + * + * @remark rd_kafka_mem_free() must only be used for pointers returned by APIs + * that explicitly mention using this function for freeing. + */ +RD_EXPORT +void rd_kafka_mem_free (rd_kafka_t *rk, void *ptr); + + +/**@}*/ + + + + + +/** + * @name Queue API + * @{ + * + * Message queues allows the application to re-route consumed messages + * from multiple topic+partitions into one single queue point. + * This queue point containing messages from a number of topic+partitions + * may then be served by a single rd_kafka_consume*_queue() call, + * rather than one call per topic+partition combination. + */ + + +/** + * @brief Create a new message queue. + * + * See rd_kafka_consume_start_queue(), rd_kafka_consume_queue(), et.al. + */ +RD_EXPORT +rd_kafka_queue_t *rd_kafka_queue_new(rd_kafka_t *rk); + +/** + * Destroy a queue, purging all of its enqueued messages. + */ +RD_EXPORT +void rd_kafka_queue_destroy(rd_kafka_queue_t *rkqu); + + +/** + * @returns a reference to the main librdkafka event queue. + * This is the queue served by rd_kafka_poll(). + * + * Use rd_kafka_queue_destroy() to loose the reference. + */ +RD_EXPORT +rd_kafka_queue_t *rd_kafka_queue_get_main (rd_kafka_t *rk); + + +/** + * @returns a reference to the librdkafka consumer queue. + * This is the queue served by rd_kafka_consumer_poll(). + * + * Use rd_kafka_queue_destroy() to loose the reference. + * + * @remark rd_kafka_queue_destroy() MUST be called on this queue + * prior to calling rd_kafka_consumer_close(). + */ +RD_EXPORT +rd_kafka_queue_t *rd_kafka_queue_get_consumer (rd_kafka_t *rk); + +/** + * @returns a reference to the partition's queue, or NULL if + * partition is invalid. + * + * Use rd_kafka_queue_destroy() to loose the reference. + * + * @remark rd_kafka_queue_destroy() MUST be called on this queue + * + * @remark This function only works on consumers. + */ +RD_EXPORT +rd_kafka_queue_t *rd_kafka_queue_get_partition (rd_kafka_t *rk, + const char *topic, + int32_t partition); + +/** + * @brief Forward/re-route queue \p src to \p dst. + * If \p dst is \c NULL the forwarding is removed. + * + * The internal refcounts for both queues are increased. + * + * @remark Regardless of whether \p dst is NULL or not, after calling this + * function, \p src will not forward it's fetch queue to the consumer + * queue. + */ +RD_EXPORT +void rd_kafka_queue_forward (rd_kafka_queue_t *src, rd_kafka_queue_t *dst); + +/** + * @brief Forward librdkafka logs (and debug) to the specified queue + * for serving with one of the ..poll() calls. + * + * This allows an application to serve log callbacks (\c log_cb) + * in its thread of choice. + * + * @param rkqu Queue to forward logs to. If the value is NULL the logs + * are forwarded to the main queue. + * + * @remark The configuration property \c log.queue MUST also be set to true. + * + * @remark librdkafka maintains its own reference to the provided queue. + * + * @returns RD_KAFKA_RESP_ERR_NO_ERROR on success or an error code on error. + */ +RD_EXPORT +rd_kafka_resp_err_t rd_kafka_set_log_queue (rd_kafka_t *rk, + rd_kafka_queue_t *rkqu); + + +/** + * @returns the current number of elements in queue. + */ +RD_EXPORT +size_t rd_kafka_queue_length (rd_kafka_queue_t *rkqu); + + +/** + * @brief Enable IO event triggering for queue. + * + * To ease integration with IO based polling loops this API + * allows an application to create a separate file-descriptor + * that librdkafka will write \p payload (of size \p size) to + * whenever a new element is enqueued on a previously empty queue. + * + * To remove event triggering call with \p fd = -1. + * + * librdkafka will maintain a copy of the \p payload. + * + * @remark When using forwarded queues the IO event must only be enabled + * on the final forwarded-to (destination) queue. + */ +RD_EXPORT +void rd_kafka_queue_io_event_enable (rd_kafka_queue_t *rkqu, int fd, + const void *payload, size_t size); + +/**@}*/ + +/** + * + * @name Simple Consumer API (legacy) + * @{ + * + */ + + +#define RD_KAFKA_OFFSET_BEGINNING -2 /**< Start consuming from beginning of + * kafka partition queue: oldest msg */ +#define RD_KAFKA_OFFSET_END -1 /**< Start consuming from end of kafka + * partition queue: next msg */ +#define RD_KAFKA_OFFSET_STORED -1000 /**< Start consuming from offset retrieved + * from offset store */ +#define RD_KAFKA_OFFSET_INVALID -1001 /**< Invalid offset */ + + +/** @cond NO_DOC */ +#define RD_KAFKA_OFFSET_TAIL_BASE -2000 /* internal: do not use */ +/** @endcond */ + +/** + * @brief Start consuming \p CNT messages from topic's current end offset. + * + * That is, if current end offset is 12345 and \p CNT is 200, it will start + * consuming from offset \c 12345-200 = \c 12145. */ +#define RD_KAFKA_OFFSET_TAIL(CNT) (RD_KAFKA_OFFSET_TAIL_BASE - (CNT)) + +/** + * @brief Start consuming messages for topic \p rkt and \p partition + * at offset \p offset which may either be an absolute \c (0..N) + * or one of the logical offsets: + * - RD_KAFKA_OFFSET_BEGINNING + * - RD_KAFKA_OFFSET_END + * - RD_KAFKA_OFFSET_STORED + * - RD_KAFKA_OFFSET_TAIL + * + * rdkafka will attempt to keep \c queued.min.messages (config property) + * messages in the local queue by repeatedly fetching batches of messages + * from the broker until the threshold is reached. + * + * The application shall use one of the `rd_kafka_consume*()` functions + * to consume messages from the local queue, each kafka message being + * represented as a `rd_kafka_message_t *` object. + * + * `rd_kafka_consume_start()` must not be called multiple times for the same + * topic and partition without stopping consumption first with + * `rd_kafka_consume_stop()`. + * + * @returns 0 on success or -1 on error in which case errno is set accordingly: + * - EBUSY - Conflicts with an existing or previous subscription + * (RD_KAFKA_RESP_ERR__CONFLICT) + * - EINVAL - Invalid offset, or incomplete configuration (lacking group.id) + * (RD_KAFKA_RESP_ERR__INVALID_ARG) + * - ESRCH - requested \p partition is invalid. + * (RD_KAFKA_RESP_ERR__UNKNOWN_PARTITION) + * - ENOENT - topic is unknown in the Kafka cluster. + * (RD_KAFKA_RESP_ERR__UNKNOWN_TOPIC) + * + * Use `rd_kafka_errno2err()` to convert sytem \c errno to `rd_kafka_resp_err_t` + */ +RD_EXPORT +int rd_kafka_consume_start(rd_kafka_topic_t *rkt, int32_t partition, + int64_t offset); + +/** + * @brief Same as rd_kafka_consume_start() but re-routes incoming messages to + * the provided queue \p rkqu (which must have been previously allocated + * with `rd_kafka_queue_new()`. + * + * The application must use one of the `rd_kafka_consume_*_queue()` functions + * to receive fetched messages. + * + * `rd_kafka_consume_start_queue()` must not be called multiple times for the + * same topic and partition without stopping consumption first with + * `rd_kafka_consume_stop()`. + * `rd_kafka_consume_start()` and `rd_kafka_consume_start_queue()` must not + * be combined for the same topic and partition. + */ +RD_EXPORT +int rd_kafka_consume_start_queue(rd_kafka_topic_t *rkt, int32_t partition, + int64_t offset, rd_kafka_queue_t *rkqu); + +/** + * @brief Stop consuming messages for topic \p rkt and \p partition, purging + * all messages currently in the local queue. + * + * NOTE: To enforce synchronisation this call will block until the internal + * fetcher has terminated and offsets are committed to configured + * storage method. + * + * The application needs to be stop all consumers before calling + * `rd_kafka_destroy()` on the main object handle. + * + * @returns 0 on success or -1 on error (see `errno`). + */ +RD_EXPORT +int rd_kafka_consume_stop(rd_kafka_topic_t *rkt, int32_t partition); + + + +/** + * @brief Seek consumer for topic+partition to \p offset which is either an + * absolute or logical offset. + * + * If \p timeout_ms is not 0 the call will wait this long for the + * seek to be performed. If the timeout is reached the internal state + * will be unknown and this function returns `RD_KAFKA_RESP_ERR__TIMED_OUT`. + * If \p timeout_ms is 0 it will initiate the seek but return + * immediately without any error reporting (e.g., async). + * + * This call triggers a fetch queue barrier flush. + * + * @returns `RD_KAFKA_RESP_ERR__NO_ERROR` on success else an error code. + */ +RD_EXPORT +rd_kafka_resp_err_t rd_kafka_seek (rd_kafka_topic_t *rkt, + int32_t partition, + int64_t offset, + int timeout_ms); + + +/** + * @brief Consume a single message from topic \p rkt and \p partition + * + * \p timeout_ms is maximum amount of time to wait for a message to be received. + * Consumer must have been previously started with `rd_kafka_consume_start()`. + * + * @returns a message object on success or \c NULL on error. + * The message object must be destroyed with `rd_kafka_message_destroy()` + * when the application is done with it. + * + * Errors (when returning NULL): + * - ETIMEDOUT - \p timeout_ms was reached with no new messages fetched. + * - ENOENT - \p rkt + \p partition is unknown. + * (no prior `rd_kafka_consume_start()` call) + * + * NOTE: The returned message's \c ..->err must be checked for errors. + * NOTE: \c ..->err \c == \c RD_KAFKA_RESP_ERR__PARTITION_EOF signals that the + * end of the partition has been reached, which should typically not be + * considered an error. The application should handle this case + * (e.g., ignore). + * + * @remark on_consume() interceptors may be called from this function prior to + * passing message to application. + */ +RD_EXPORT +rd_kafka_message_t *rd_kafka_consume(rd_kafka_topic_t *rkt, int32_t partition, + int timeout_ms); + + + +/** + * @brief Consume up to \p rkmessages_size from topic \p rkt and \p partition + * putting a pointer to each message in the application provided + * array \p rkmessages (of size \p rkmessages_size entries). + * + * `rd_kafka_consume_batch()` provides higher throughput performance + * than `rd_kafka_consume()`. + * + * \p timeout_ms is the maximum amount of time to wait for all of + * \p rkmessages_size messages to be put into \p rkmessages. + * If no messages were available within the timeout period this function + * returns 0 and \p rkmessages remains untouched. + * This differs somewhat from `rd_kafka_consume()`. + * + * The message objects must be destroyed with `rd_kafka_message_destroy()` + * when the application is done with it. + * + * @returns the number of rkmessages added in \p rkmessages, + * or -1 on error (same error codes as for `rd_kafka_consume()`. + * + * @sa rd_kafka_consume() + * + * @remark on_consume() interceptors may be called from this function prior to + * passing message to application. + */ +RD_EXPORT +ssize_t rd_kafka_consume_batch(rd_kafka_topic_t *rkt, int32_t partition, + int timeout_ms, + rd_kafka_message_t **rkmessages, + size_t rkmessages_size); + + + +/** + * @brief Consumes messages from topic \p rkt and \p partition, calling + * the provided callback for each consumed messsage. + * + * `rd_kafka_consume_callback()` provides higher throughput performance + * than both `rd_kafka_consume()` and `rd_kafka_consume_batch()`. + * + * \p timeout_ms is the maximum amount of time to wait for one or more messages + * to arrive. + * + * The provided \p consume_cb function is called for each message, + * the application \b MUST \b NOT call `rd_kafka_message_destroy()` on the + * provided \p rkmessage. + * + * The \p opaque argument is passed to the 'consume_cb' as \p opaque. + * + * @returns the number of messages processed or -1 on error. + * + * @sa rd_kafka_consume() + * + * @remark on_consume() interceptors may be called from this function prior to + * passing message to application. + */ +RD_EXPORT +int rd_kafka_consume_callback(rd_kafka_topic_t *rkt, int32_t partition, + int timeout_ms, + void (*consume_cb) (rd_kafka_message_t + *rkmessage, + void *opaque), + void *opaque); + + +/** + * @name Simple Consumer API (legacy): Queue consumers + * @{ + * + * The following `..._queue()` functions are analogue to the functions above + * but reads messages from the provided queue \p rkqu instead. + * \p rkqu must have been previously created with `rd_kafka_queue_new()` + * and the topic consumer must have been started with + * `rd_kafka_consume_start_queue()` utilising the the same queue. + */ + +/** + * @brief Consume from queue + * + * @sa rd_kafka_consume() + */ +RD_EXPORT +rd_kafka_message_t *rd_kafka_consume_queue(rd_kafka_queue_t *rkqu, + int timeout_ms); + +/** + * @brief Consume batch of messages from queue + * + * @sa rd_kafka_consume_batch() + */ +RD_EXPORT +ssize_t rd_kafka_consume_batch_queue(rd_kafka_queue_t *rkqu, + int timeout_ms, + rd_kafka_message_t **rkmessages, + size_t rkmessages_size); + +/** + * @brief Consume multiple messages from queue with callback + * + * @sa rd_kafka_consume_callback() + */ +RD_EXPORT +int rd_kafka_consume_callback_queue(rd_kafka_queue_t *rkqu, + int timeout_ms, + void (*consume_cb) (rd_kafka_message_t + *rkmessage, + void *opaque), + void *opaque); + + +/**@}*/ + + + + +/** + * @name Simple Consumer API (legacy): Topic+partition offset store. + * @{ + * + * If \c auto.commit.enable is true the offset is stored automatically prior to + * returning of the message(s) in each of the rd_kafka_consume*() functions + * above. + */ + + +/** + * @brief Store offset \p offset for topic \p rkt partition \p partition. + * + * The offset will be committed (written) to the offset store according + * to \c `auto.commit.interval.ms` or manual offset-less commit() + * + * @remark \c `enable.auto.offset.store` must be set to "false" when using this API. + * + * @returns RD_KAFKA_RESP_ERR_NO_ERROR on success or an error code on error. + */ +RD_EXPORT +rd_kafka_resp_err_t rd_kafka_offset_store(rd_kafka_topic_t *rkt, + int32_t partition, int64_t offset); + + +/** + * @brief Store offsets for next auto-commit for one or more partitions. + * + * The offset will be committed (written) to the offset store according + * to \c `auto.commit.interval.ms` or manual offset-less commit(). + * + * Per-partition success/error status propagated through each partition's + * \c .err field. + * + * @remark \c `enable.auto.offset.store` must be set to "false" when using this API. + * + * @returns RD_KAFKA_RESP_ERR_NO_ERROR on success, or + * RD_KAFKA_RESP_ERR__UNKNOWN_PARTITION if none of the + * offsets could be stored, or + * RD_KAFKA_RESP_ERR__INVALID_ARG if \c enable.auto.offset.store is true. + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_offsets_store(rd_kafka_t *rk, + rd_kafka_topic_partition_list_t *offsets); +/**@}*/ + + + + +/** + * @name KafkaConsumer (C) + * @{ + * @brief High-level KafkaConsumer C API + * + * + * + */ + +/** + * @brief Subscribe to topic set using balanced consumer groups. + * + * Wildcard (regex) topics are supported by the librdkafka assignor: + * any topic name in the \p topics list that is prefixed with \c \"^\" will + * be regex-matched to the full list of topics in the cluster and matching + * topics will be added to the subscription list. + * + * @returns RD_KAFKA_RESP_ERR_NO_ERROR on success or + * RD_KAFKA_RESP_ERR__INVALID_ARG if list is empty, contains invalid + * topics or regexes. + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_subscribe (rd_kafka_t *rk, + const rd_kafka_topic_partition_list_t *topics); + + +/** + * @brief Unsubscribe from the current subscription set. + */ +RD_EXPORT +rd_kafka_resp_err_t rd_kafka_unsubscribe (rd_kafka_t *rk); + + +/** + * @brief Returns the current topic subscription + * + * @returns An error code on failure, otherwise \p topic is updated + * to point to a newly allocated topic list (possibly empty). + * + * @remark The application is responsible for calling + * rd_kafka_topic_partition_list_destroy on the returned list. + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_subscription (rd_kafka_t *rk, + rd_kafka_topic_partition_list_t **topics); + + + +/** + * @brief Poll the consumer for messages or events. + * + * Will block for at most \p timeout_ms milliseconds. + * + * @remark An application should make sure to call consumer_poll() at regular + * intervals, even if no messages are expected, to serve any + * queued callbacks waiting to be called. This is especially + * important when a rebalance_cb has been registered as it needs + * to be called and handled properly to synchronize internal + * consumer state. + * + * @returns A message object which is a proper message if \p ->err is + * RD_KAFKA_RESP_ERR_NO_ERROR, or an event or error for any other + * value. + * + * @remark on_consume() interceptors may be called from this function prior to + * passing message to application. + * + * @sa rd_kafka_message_t + */ +RD_EXPORT +rd_kafka_message_t *rd_kafka_consumer_poll (rd_kafka_t *rk, int timeout_ms); + +/** + * @brief Close down the KafkaConsumer. + * + * @remark This call will block until the consumer has revoked its assignment, + * calling the \c rebalance_cb if it is configured, committed offsets + * to broker, and left the consumer group. + * The maximum blocking time is roughly limited to session.timeout.ms. + * + * @returns An error code indicating if the consumer close was succesful + * or not. + * + * @remark The application still needs to call rd_kafka_destroy() after + * this call finishes to clean up the underlying handle resources. + * + */ +RD_EXPORT +rd_kafka_resp_err_t rd_kafka_consumer_close (rd_kafka_t *rk); + + + +/** + * @brief Atomic assignment of partitions to consume. + * + * The new \p partitions will replace the existing assignment. + * + * When used from a rebalance callback the application shall pass the + * partition list passed to the callback (or a copy of it) (even if the list + * is empty) rather than NULL to maintain internal join state. + + * A zero-length \p partitions will treat the partitions as a valid, + * albeit empty, assignment, and maintain internal state, while a \c NULL + * value for \p partitions will reset and clear the internal state. + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_assign (rd_kafka_t *rk, + const rd_kafka_topic_partition_list_t *partitions); + +/** + * @brief Returns the current partition assignment + * + * @returns An error code on failure, otherwise \p partitions is updated + * to point to a newly allocated partition list (possibly empty). + * + * @remark The application is responsible for calling + * rd_kafka_topic_partition_list_destroy on the returned list. + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_assignment (rd_kafka_t *rk, + rd_kafka_topic_partition_list_t **partitions); + + + + +/** + * @brief Commit offsets on broker for the provided list of partitions. + * + * \p offsets should contain \c topic, \c partition, \c offset and possibly + * \c metadata. + * If \p offsets is NULL the current partition assignment will be used instead. + * + * If \p async is false this operation will block until the broker offset commit + * is done, returning the resulting success or error code. + * + * If a rd_kafka_conf_set_offset_commit_cb() offset commit callback has been + * configured the callback will be enqueued for a future call to + * rd_kafka_poll(), rd_kafka_consumer_poll() or similar. + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_commit (rd_kafka_t *rk, const rd_kafka_topic_partition_list_t *offsets, + int async); + + +/** + * @brief Commit message's offset on broker for the message's partition. + * + * @sa rd_kafka_commit + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_commit_message (rd_kafka_t *rk, const rd_kafka_message_t *rkmessage, + int async); + + +/** + * @brief Commit offsets on broker for the provided list of partitions. + * + * See rd_kafka_commit for \p offsets semantics. + * + * The result of the offset commit will be posted on the provided \p rkqu queue. + * + * If the application uses one of the poll APIs (rd_kafka_poll(), + * rd_kafka_consumer_poll(), rd_kafka_queue_poll(), ..) to serve the queue + * the \p cb callback is required. \p opaque is passed to the callback. + * + * If using the event API the callback is ignored and the offset commit result + * will be returned as an RD_KAFKA_EVENT_COMMIT event. The \p opaque + * value will be available with rd_kafka_event_opaque() + * + * If \p rkqu is NULL a temporary queue will be created and the callback will + * be served by this call. + * + * @sa rd_kafka_commit() + * @sa rd_kafka_conf_set_offset_commit_cb() + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_commit_queue (rd_kafka_t *rk, + const rd_kafka_topic_partition_list_t *offsets, + rd_kafka_queue_t *rkqu, + void (*cb) (rd_kafka_t *rk, + rd_kafka_resp_err_t err, + rd_kafka_topic_partition_list_t *offsets, + void *opaque), + void *opaque); + + +/** + * @brief Retrieve committed offsets for topics+partitions. + * + * The \p offset field of each requested partition will either be set to + * stored offset or to RD_KAFKA_OFFSET_INVALID in case there was no stored + * offset for that partition. + * + * @returns RD_KAFKA_RESP_ERR_NO_ERROR on success in which case the + * \p offset or \p err field of each \p partitions' element is filled + * in with the stored offset, or a partition specific error. + * Else returns an error code. + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_committed (rd_kafka_t *rk, + rd_kafka_topic_partition_list_t *partitions, + int timeout_ms); + + + +/** + * @brief Retrieve current positions (offsets) for topics+partitions. + * + * The \p offset field of each requested partition will be set to the offset + * of the last consumed message + 1, or RD_KAFKA_OFFSET_INVALID in case there was + * no previous message. + * + * @returns RD_KAFKA_RESP_ERR_NO_ERROR on success in which case the + * \p offset or \p err field of each \p partitions' element is filled + * in with the stored offset, or a partition specific error. + * Else returns an error code. + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_position (rd_kafka_t *rk, + rd_kafka_topic_partition_list_t *partitions); + + +/**@}*/ + + + +/** + * @name Producer API + * @{ + * + * + */ + + +/** + * @brief Producer message flags + */ +#define RD_KAFKA_MSG_F_FREE 0x1 /**< Delegate freeing of payload to rdkafka. */ +#define RD_KAFKA_MSG_F_COPY 0x2 /**< rdkafka will make a copy of the payload. */ +#define RD_KAFKA_MSG_F_BLOCK 0x4 /**< Block produce*() on message queue full. + * WARNING: If a delivery report callback + * is used the application MUST + * call rd_kafka_poll() (or equiv.) + * to make sure delivered messages + * are drained from the internal + * delivery report queue. + * Failure to do so will result + * in indefinately blocking on + * the produce() call when the + * message queue is full. + */ + + + +/** + * @brief Produce and send a single message to broker. + * + * \p rkt is the target topic which must have been previously created with + * `rd_kafka_topic_new()`. + * + * `rd_kafka_produce()` is an asynch non-blocking API. + * + * \p partition is the target partition, either: + * - RD_KAFKA_PARTITION_UA (unassigned) for + * automatic partitioning using the topic's partitioner function, or + * - a fixed partition (0..N) + * + * \p msgflags is zero or more of the following flags OR:ed together: + * RD_KAFKA_MSG_F_BLOCK - block \p produce*() call if + * \p queue.buffering.max.messages or + * \p queue.buffering.max.kbytes are exceeded. + * Messages are considered in-queue from the point they + * are accepted by produce() until their corresponding + * delivery report callback/event returns. + * It is thus a requirement to call + * rd_kafka_poll() (or equiv.) from a separate + * thread when F_BLOCK is used. + * See WARNING on \c RD_KAFKA_MSG_F_BLOCK above. + * + * RD_KAFKA_MSG_F_FREE - rdkafka will free(3) \p payload when it is done + * with it. + * RD_KAFKA_MSG_F_COPY - the \p payload data will be copied and the + * \p payload pointer will not be used by rdkafka + * after the call returns. + * + * .._F_FREE and .._F_COPY are mutually exclusive. + * + * If the function returns -1 and RD_KAFKA_MSG_F_FREE was specified, then + * the memory associated with the payload is still the caller's + * responsibility. + * + * \p payload is the message payload of size \p len bytes. + * + * \p key is an optional message key of size \p keylen bytes, if non-NULL it + * will be passed to the topic partitioner as well as be sent with the + * message to the broker and passed on to the consumer. + * + * \p msg_opaque is an optional application-provided per-message opaque + * pointer that will provided in the delivery report callback (`dr_cb`) for + * referencing this message. + * + * @remark on_send() and on_acknowledgement() interceptors may be called + * from this function. on_acknowledgement() will only be called if the + * message fails partitioning. + * + * @returns 0 on success or -1 on error in which case errno is set accordingly: + * - ENOBUFS - maximum number of outstanding messages has been reached: + * "queue.buffering.max.messages" + * (RD_KAFKA_RESP_ERR__QUEUE_FULL) + * - EMSGSIZE - message is larger than configured max size: + * "messages.max.bytes". + * (RD_KAFKA_RESP_ERR_MSG_SIZE_TOO_LARGE) + * - ESRCH - requested \p partition is unknown in the Kafka cluster. + * (RD_KAFKA_RESP_ERR__UNKNOWN_PARTITION) + * - ENOENT - topic is unknown in the Kafka cluster. + * (RD_KAFKA_RESP_ERR__UNKNOWN_TOPIC) + * + * @sa Use rd_kafka_errno2err() to convert `errno` to rdkafka error code. + */ +RD_EXPORT +int rd_kafka_produce(rd_kafka_topic_t *rkt, int32_t partition, + int msgflags, + void *payload, size_t len, + const void *key, size_t keylen, + void *msg_opaque); + + +/** + * @brief Produce and send a single message to broker. + * + * The message is defined by a va-arg list using \c rd_kafka_vtype_t + * tag tuples which must be terminated with a single \c RD_KAFKA_V_END. + * + * @returns \c RD_KAFKA_RESP_ERR_NO_ERROR on success, else an error code. + * \c RD_KAFKA_RESP_ERR__CONFLICT is returned if _V_HEADER and + * _V_HEADERS are mixed. + * + * @sa rd_kafka_produce, RD_KAFKA_V_END + */ +RD_EXPORT +rd_kafka_resp_err_t rd_kafka_producev (rd_kafka_t *rk, ...); + + +/** + * @brief Produce multiple messages. + * + * If partition is RD_KAFKA_PARTITION_UA the configured partitioner will + * be run for each message (slower), otherwise the messages will be enqueued + * to the specified partition directly (faster). + * + * The messages are provided in the array \p rkmessages of count \p message_cnt + * elements. + * The \p partition and \p msgflags are used for all provided messages. + * + * Honoured \p rkmessages[] fields are: + * - payload,len Message payload and length + * - key,key_len Optional message key + * - _private Message opaque pointer (msg_opaque) + * - err Will be set according to success or failure. + * Application only needs to check for errors if + * return value != \p message_cnt. + * + * @returns the number of messages succesfully enqueued for producing. + * + * @remark This interface does NOT support setting message headers on + * the provided \p rkmessages. + */ +RD_EXPORT +int rd_kafka_produce_batch(rd_kafka_topic_t *rkt, int32_t partition, + int msgflags, + rd_kafka_message_t *rkmessages, int message_cnt); + + + + +/** + * @brief Wait until all outstanding produce requests, et.al, are completed. + * This should typically be done prior to destroying a producer instance + * to make sure all queued and in-flight produce requests are completed + * before terminating. + * + * @remark This function will call rd_kafka_poll() and thus trigger callbacks. + * + * @returns RD_KAFKA_RESP_ERR__TIMED_OUT if \p timeout_ms was reached before all + * outstanding requests were completed, else RD_KAFKA_RESP_ERR_NO_ERROR + */ +RD_EXPORT +rd_kafka_resp_err_t rd_kafka_flush (rd_kafka_t *rk, int timeout_ms); + + +/**@}*/ + + +/** +* @name Metadata API +* @{ +* +* +*/ + + +/** + * @brief Broker information + */ +typedef struct rd_kafka_metadata_broker { + int32_t id; /**< Broker Id */ + char *host; /**< Broker hostname */ + int port; /**< Broker listening port */ +} rd_kafka_metadata_broker_t; + +/** + * @brief Partition information + */ +typedef struct rd_kafka_metadata_partition { + int32_t id; /**< Partition Id */ + rd_kafka_resp_err_t err; /**< Partition error reported by broker */ + int32_t leader; /**< Leader broker */ + int replica_cnt; /**< Number of brokers in \p replicas */ + int32_t *replicas; /**< Replica brokers */ + int isr_cnt; /**< Number of ISR brokers in \p isrs */ + int32_t *isrs; /**< In-Sync-Replica brokers */ +} rd_kafka_metadata_partition_t; + +/** + * @brief Topic information + */ +typedef struct rd_kafka_metadata_topic { + char *topic; /**< Topic name */ + int partition_cnt; /**< Number of partitions in \p partitions*/ + struct rd_kafka_metadata_partition *partitions; /**< Partitions */ + rd_kafka_resp_err_t err; /**< Topic error reported by broker */ +} rd_kafka_metadata_topic_t; + + +/** + * @brief Metadata container + */ +typedef struct rd_kafka_metadata { + int broker_cnt; /**< Number of brokers in \p brokers */ + struct rd_kafka_metadata_broker *brokers; /**< Brokers */ + + int topic_cnt; /**< Number of topics in \p topics */ + struct rd_kafka_metadata_topic *topics; /**< Topics */ + + int32_t orig_broker_id; /**< Broker originating this metadata */ + char *orig_broker_name; /**< Name of originating broker */ +} rd_kafka_metadata_t; + + +/** + * @brief Request Metadata from broker. + * + * Parameters: + * - \p all_topics if non-zero: request info about all topics in cluster, + * if zero: only request info about locally known topics. + * - \p only_rkt only request info about this topic + * - \p metadatap pointer to hold metadata result. + * The \p *metadatap pointer must be released + * with rd_kafka_metadata_destroy(). + * - \p timeout_ms maximum response time before failing. + * + * Returns RD_KAFKA_RESP_ERR_NO_ERROR on success (in which case *metadatap) + * will be set, else RD_KAFKA_RESP_ERR__TIMED_OUT on timeout or + * other error code on error. + */ +RD_EXPORT +rd_kafka_resp_err_t +rd_kafka_metadata (rd_kafka_t *rk, int all_topics, + rd_kafka_topic_t *only_rkt, + const struct rd_kafka_metadata **metadatap, + int timeout_ms); + +/** + * @brief Release metadata memory. + */ +RD_EXPORT +void rd_kafka_metadata_destroy(const struct rd_kafka_metadata *metadata); + + +/**@}*/ + + + +/** +* @name Client group information +* @{ +* +* +*/ + + +/** + * @brief Group member information + * + * For more information on \p member_metadata format, see + * https://cwiki.apache.org/confluence/display/KAFKA/A+Guide+To+The+Kafka+Protocol#AGuideToTheKafkaProtocol-GroupMembershipAPI + * + */ +struct rd_kafka_group_member_info { + char *member_id; /**< Member id (generated by broker) */ + char *client_id; /**< Client's \p client.id */ + char *client_host; /**< Client's hostname */ + void *member_metadata; /**< Member metadata (binary), + * format depends on \p protocol_type. */ + int member_metadata_size; /**< Member metadata size in bytes */ + void *member_assignment; /**< Member assignment (binary), + * format depends on \p protocol_type. */ + int member_assignment_size; /**< Member assignment size in bytes */ +}; + +/** + * @brief Group information + */ +struct rd_kafka_group_info { + struct rd_kafka_metadata_broker broker; /**< Originating broker info */ + char *group; /**< Group name */ + rd_kafka_resp_err_t err; /**< Broker-originated error */ + char *state; /**< Group state */ + char *protocol_type; /**< Group protocol type */ + char *protocol; /**< Group protocol */ + struct rd_kafka_group_member_info *members; /**< Group members */ + int member_cnt; /**< Group member count */ +}; + +/** + * @brief List of groups + * + * @sa rd_kafka_group_list_destroy() to release list memory. + */ +struct rd_kafka_group_list { + struct rd_kafka_group_info *groups; /**< Groups */ + int group_cnt; /**< Group count */ +}; + + +/** + * @brief List and describe client groups in cluster. + * + * \p group is an optional group name to describe, otherwise (\p NULL) all + * groups are returned. + * + * \p timeout_ms is the (approximate) maximum time to wait for response + * from brokers and must be a positive value. + * + * @returns \c RD_KAFKA_RESP_ERR__NO_ERROR on success and \p grplistp is + * updated to point to a newly allocated list of groups. + * \c RD_KAFKA_RESP_ERR__PARTIAL if not all brokers responded + * in time but at least one group is returned in \p grplistlp. + * \c RD_KAFKA_RESP_ERR__TIMED_OUT if no groups were returned in the + * given timeframe but not all brokers have yet responded, or + * if the list of brokers in the cluster could not be obtained within + * the given timeframe. + * \c RD_KAFKA_RESP_ERR__TRANSPORT if no brokers were found. + * Other error codes may also be returned from the request layer. + * + * The \p grplistp remains untouched if any error code is returned, + * with the exception of RD_KAFKA_RESP_ERR__PARTIAL which behaves + * as RD_KAFKA_RESP_ERR__NO_ERROR (success) but with an incomplete + * group list. + * + * @sa Use rd_kafka_group_list_destroy() to release list memory. + */ +RD_EXPORT +rd_kafka_resp_err_t +rd_kafka_list_groups (rd_kafka_t *rk, const char *group, + const struct rd_kafka_group_list **grplistp, + int timeout_ms); + +/** + * @brief Release list memory + */ +RD_EXPORT +void rd_kafka_group_list_destroy (const struct rd_kafka_group_list *grplist); + + +/**@}*/ + + + +/** + * @name Miscellaneous APIs + * @{ + * + */ + + +/** + * @brief Adds one or more brokers to the kafka handle's list of initial + * bootstrap brokers. + * + * Additional brokers will be discovered automatically as soon as rdkafka + * connects to a broker by querying the broker metadata. + * + * If a broker name resolves to multiple addresses (and possibly + * address families) all will be used for connection attempts in + * round-robin fashion. + * + * \p brokerlist is a ,-separated list of brokers in the format: + * \c \<broker1\>,\<broker2\>,.. + * Where each broker is in either the host or URL based format: + * \c \<host\>[:\<port\>] + * \c \<proto\>://\<host\>[:port] + * \c \<proto\> is either \c PLAINTEXT, \c SSL, \c SASL, \c SASL_PLAINTEXT + * The two formats can be mixed but ultimately the value of the + * `security.protocol` config property decides what brokers are allowed. + * + * Example: + * brokerlist = "broker1:10000,broker2" + * brokerlist = "SSL://broker3:9000,ssl://broker2" + * + * @returns the number of brokers successfully added. + * + * @remark Brokers may also be defined with the \c metadata.broker.list or + * \c bootstrap.servers configuration property (preferred method). + */ +RD_EXPORT +int rd_kafka_brokers_add(rd_kafka_t *rk, const char *brokerlist); + + + + +/** + * @brief Set logger function. + * + * The default is to print to stderr, but a syslog logger is also available, + * see rd_kafka_log_(print|syslog) for the builtin alternatives. + * Alternatively the application may provide its own logger callback. + * Or pass 'func' as NULL to disable logging. + * + * @deprecated Use rd_kafka_conf_set_log_cb() + * + * @remark \p rk may be passed as NULL in the callback. + */ +RD_EXPORT RD_DEPRECATED +void rd_kafka_set_logger(rd_kafka_t *rk, + void (*func) (const rd_kafka_t *rk, int level, + const char *fac, const char *buf)); + + +/** + * @brief Specifies the maximum logging level produced by + * internal kafka logging and debugging. + * + * If the \p \"debug\" configuration property is set the level is automatically + * adjusted to \c LOG_DEBUG (7). + */ +RD_EXPORT +void rd_kafka_set_log_level(rd_kafka_t *rk, int level); + + +/** + * @brief Builtin (default) log sink: print to stderr + */ +RD_EXPORT +void rd_kafka_log_print(const rd_kafka_t *rk, int level, + const char *fac, const char *buf); + + +/** + * @brief Builtin log sink: print to syslog. + */ +RD_EXPORT +void rd_kafka_log_syslog(const rd_kafka_t *rk, int level, + const char *fac, const char *buf); + + +/** + * @brief Returns the current out queue length. + * + * The out queue contains messages waiting to be sent to, or acknowledged by, + * the broker. + * + * An application should wait for this queue to reach zero before terminating + * to make sure outstanding requests (such as offset commits) are fully + * processed. + * + * @returns number of messages in the out queue. + */ +RD_EXPORT +int rd_kafka_outq_len(rd_kafka_t *rk); + + + +/** + * @brief Dumps rdkafka's internal state for handle \p rk to stream \p fp + * + * This is only useful for debugging rdkafka, showing state and statistics + * for brokers, topics, partitions, etc. + */ +RD_EXPORT +void rd_kafka_dump(FILE *fp, rd_kafka_t *rk); + + + +/** + * @brief Retrieve the current number of threads in use by librdkafka. + * + * Used by regression tests. + */ +RD_EXPORT +int rd_kafka_thread_cnt(void); + + +/** + * @brief Wait for all rd_kafka_t objects to be destroyed. + * + * Returns 0 if all kafka objects are now destroyed, or -1 if the + * timeout was reached. + * + * @remark This function is deprecated. + */ +RD_EXPORT +int rd_kafka_wait_destroyed(int timeout_ms); + + +/** + * @brief Run librdkafka's built-in unit-tests. + * + * @returns the number of failures, or 0 if all tests passed. + */ +RD_EXPORT +int rd_kafka_unittest (void); + + +/**@}*/ + + + + +/** + * @name Experimental APIs + * @{ + */ + +/** + * @brief Redirect the main (rd_kafka_poll()) queue to the KafkaConsumer's + * queue (rd_kafka_consumer_poll()). + * + * @warning It is not permitted to call rd_kafka_poll() after directing the + * main queue with rd_kafka_poll_set_consumer(). + */ +RD_EXPORT +rd_kafka_resp_err_t rd_kafka_poll_set_consumer (rd_kafka_t *rk); + + +/**@}*/ + +/** + * @name Event interface + * + * @brief The event API provides an alternative pollable non-callback interface + * to librdkafka's message and event queues. + * + * @{ + */ + + +/** + * @brief Event types + */ +typedef int rd_kafka_event_type_t; +#define RD_KAFKA_EVENT_NONE 0x0 +#define RD_KAFKA_EVENT_DR 0x1 /**< Producer Delivery report batch */ +#define RD_KAFKA_EVENT_FETCH 0x2 /**< Fetched message (consumer) */ +#define RD_KAFKA_EVENT_LOG 0x4 /**< Log message */ +#define RD_KAFKA_EVENT_ERROR 0x8 /**< Error */ +#define RD_KAFKA_EVENT_REBALANCE 0x10 /**< Group rebalance (consumer) */ +#define RD_KAFKA_EVENT_OFFSET_COMMIT 0x20 /**< Offset commit result */ +#define RD_KAFKA_EVENT_STATS 0x40 /**< Stats */ + + +typedef struct rd_kafka_op_s rd_kafka_event_t; + + +/** + * @returns the event type for the given event. + * + * @remark As a convenience it is okay to pass \p rkev as NULL in which case + * RD_KAFKA_EVENT_NONE is returned. + */ +RD_EXPORT +rd_kafka_event_type_t rd_kafka_event_type (const rd_kafka_event_t *rkev); + +/** + * @returns the event type's name for the given event. + * + * @remark As a convenience it is okay to pass \p rkev as NULL in which case + * the name for RD_KAFKA_EVENT_NONE is returned. + */ +RD_EXPORT +const char *rd_kafka_event_name (const rd_kafka_event_t *rkev); + + +/** + * @brief Destroy an event. + * + * @remark Any references to this event, such as extracted messages, + * will not be usable after this call. + * + * @remark As a convenience it is okay to pass \p rkev as NULL in which case + * no action is performed. + */ +RD_EXPORT +void rd_kafka_event_destroy (rd_kafka_event_t *rkev); + + +/** + * @returns the next message from an event. + * + * Call repeatedly until it returns NULL. + * + * Event types: + * - RD_KAFKA_EVENT_FETCH (1 message) + * - RD_KAFKA_EVENT_DR (>=1 message(s)) + * + * @remark The returned message(s) MUST NOT be + * freed with rd_kafka_message_destroy(). + * + * @remark on_consume() interceptor may be called + * from this function prior to passing message to application. + */ +RD_EXPORT +const rd_kafka_message_t *rd_kafka_event_message_next (rd_kafka_event_t *rkev); + + +/** + * @brief Extacts \p size message(s) from the event into the + * pre-allocated array \p rkmessages. + * + * Event types: + * - RD_KAFKA_EVENT_FETCH (1 message) + * - RD_KAFKA_EVENT_DR (>=1 message(s)) + * + * @returns the number of messages extracted. + * + * @remark on_consume() interceptor may be called + * from this function prior to passing message to application. + */ +RD_EXPORT +size_t rd_kafka_event_message_array (rd_kafka_event_t *rkev, + const rd_kafka_message_t **rkmessages, + size_t size); + + +/** + * @returns the number of remaining messages in the event. + * + * Event types: + * - RD_KAFKA_EVENT_FETCH (1 message) + * - RD_KAFKA_EVENT_DR (>=1 message(s)) + */ +RD_EXPORT +size_t rd_kafka_event_message_count (rd_kafka_event_t *rkev); + + +/** + * @returns the error code for the event. + * + * Event types: + * - all + */ +RD_EXPORT +rd_kafka_resp_err_t rd_kafka_event_error (rd_kafka_event_t *rkev); + + +/** + * @returns the error string (if any). + * An application should check that rd_kafka_event_error() returns + * non-zero before calling this function. + * + * Event types: + * - all + */ +RD_EXPORT +const char *rd_kafka_event_error_string (rd_kafka_event_t *rkev); + + + +/** + * @returns the user opaque (if any) + * + * Event types: + * - RD_KAFKA_OFFSET_COMMIT + */ +RD_EXPORT +void *rd_kafka_event_opaque (rd_kafka_event_t *rkev); + + +/** + * @brief Extract log message from the event. + * + * Event types: + * - RD_KAFKA_EVENT_LOG + * + * @returns 0 on success or -1 if unsupported event type. + */ +RD_EXPORT +int rd_kafka_event_log (rd_kafka_event_t *rkev, + const char **fac, const char **str, int *level); + + +/** + * @brief Extract stats from the event. + * + * Event types: + * - RD_KAFKA_EVENT_STATS + * + * @returns stats json string. + * + * @remark the returned string will be freed automatically along with the event object + * + */ +RD_EXPORT +const char *rd_kafka_event_stats (rd_kafka_event_t *rkev); + + +/** + * @returns the topic partition list from the event. + * + * @remark The list MUST NOT be freed with rd_kafka_topic_partition_list_destroy() + * + * Event types: + * - RD_KAFKA_EVENT_REBALANCE + * - RD_KAFKA_EVENT_OFFSET_COMMIT + */ +RD_EXPORT rd_kafka_topic_partition_list_t * +rd_kafka_event_topic_partition_list (rd_kafka_event_t *rkev); + + +/** + * @returns a newly allocated topic_partition container, if applicable for the event type, + * else NULL. + * + * @remark The returned pointer MUST be freed with rd_kafka_topic_partition_destroy(). + * + * Event types: + * RD_KAFKA_EVENT_ERROR (for partition level errors) + */ +RD_EXPORT rd_kafka_topic_partition_t * +rd_kafka_event_topic_partition (rd_kafka_event_t *rkev); + + +/** + * @brief Poll a queue for an event for max \p timeout_ms. + * + * @returns an event, or NULL. + * + * @remark Use rd_kafka_event_destroy() to free the event. + */ +RD_EXPORT +rd_kafka_event_t *rd_kafka_queue_poll (rd_kafka_queue_t *rkqu, int timeout_ms); + +/** +* @brief Poll a queue for events served through callbacks for max \p timeout_ms. +* +* @returns the number of events served. +* +* @remark This API must only be used for queues with callbacks registered +* for all expected event types. E.g., not a message queue. +*/ +RD_EXPORT +int rd_kafka_queue_poll_callback (rd_kafka_queue_t *rkqu, int timeout_ms); + + +/**@}*/ + + +/** + * @name Plugin interface + * + * @brief A plugin interface that allows external runtime-loaded libraries + * to integrate with a client instance without modifications to + * the application code. + * + * Plugins are loaded when referenced through the `plugin.library.paths` + * configuration property and operates on the \c rd_kafka_conf_t + * object prior \c rd_kafka_t instance creation. + * + * @warning Plugins require the application to link librdkafka dynamically + * and not statically. Failure to do so will lead to missing symbols + * or finding symbols in another librdkafka library than the + * application was linked with. + */ + + +/** + * @brief Plugin's configuration initializer method called each time the + * library is referenced from configuration (even if previously loaded by + * another client instance). + * + * @remark This method MUST be implemented by plugins and have the symbol name + * \c conf_init + * + * @param conf Configuration set up to this point. + * @param plug_opaquep Plugin can set this pointer to a per-configuration + * opaque pointer. + * @param errstr String buffer of size \p errstr_size where plugin must write + * a human readable error string in the case the initializer + * fails (returns non-zero). + * + * @remark A plugin may add an on_conf_destroy() interceptor to clean up + * plugin-specific resources created in the plugin's conf_init() method. + * + * @returns RD_KAFKA_RESP_ERR_NO_ERROR on success or an error code on error. + */ +typedef rd_kafka_resp_err_t +(rd_kafka_plugin_f_conf_init_t) (rd_kafka_conf_t *conf, + void **plug_opaquep, + char *errstr, size_t errstr_size); + +/**@}*/ + + + +/** + * @name Interceptors + * + * @{ + * + * @brief A callback interface that allows message interception for both + * producer and consumer data pipelines. + * + * Except for the on_new(), on_conf_set(), on_conf_dup() and on_conf_destroy() + * interceptors, interceptors are added to the + * newly created rd_kafka_t client instance. These interceptors MUST only + * be added from on_new() and MUST NOT be added after rd_kafka_new() returns. + * + * The on_new(), on_conf_set(), on_conf_dup() and on_conf_destroy() interceptors + * are added to the configuration object which is later passed to + * rd_kafka_new() where on_new() is called to allow addition of + * other interceptors. + * + * Each interceptor reference consists of a display name (ic_name), + * a callback function, and an application-specified opaque value that is + * passed as-is to the callback. + * The ic_name must be unique for the interceptor implementation and is used + * to reject duplicate interceptor methods. + * + * Any number of interceptors can be added and they are called in the order + * they were added, unless otherwise noted. + * The list of registered interceptor methods are referred to as + * interceptor chains. + * + * @remark Contrary to the Java client the librdkafka interceptor interface + * does not support message key and value modification. + * Message mutability is discouraged in the Java client and the + * combination of serializers and headers cover most use-cases. + * + * @remark Interceptors are NOT copied to the new configuration on + * rd_kafka_conf_dup() since it would be hard for interceptors to + * track usage of the interceptor's opaque value. + * An interceptor should rely on the plugin, which will be copied + * in rd_kafka_conf_conf_dup(), to set up the initial interceptors. + * An interceptor should implement the on_conf_dup() method + * to manually set up its internal configuration on the newly created + * configuration object that is being copied-to based on the + * interceptor-specific configuration properties. + * conf_dup() should thus be treated the same as conf_init(). + * + * @remark Interceptors are keyed by the interceptor type (on_..()), the + * interceptor name (ic_name) and the interceptor method function. + * Duplicates are not allowed and the .._add_on_..() method will + * return RD_KAFKA_RESP_ERR__CONFLICT if attempting to add a duplicate + * method. + * The only exception is on_conf_destroy() which may be added multiple + * times by the same interceptor to allow proper cleanup of + * interceptor configuration state. + */ + + +/** + * @brief on_conf_set() is called from rd_kafka_*_conf_set() in the order + * the interceptors were added. + * + * @param ic_opaque The interceptor's opaque pointer specified in ..add..(). + * @param name The configuration property to set. + * @param val The configuration value to set, or NULL for reverting to default + * in which case the previous value should be freed. + * @param errstr A human readable error string in case the interceptor fails. + * @param errstr_size Maximum space (including \0) in \p errstr. + * + * @returns RD_KAFKA_CONF_RES_OK if the property was known and successfully + * handled by the interceptor, RD_KAFKA_CONF_RES_INVALID if the + * property was handled by the interceptor but the value was invalid, + * or RD_KAFKA_CONF_RES_UNKNOWN if the interceptor did not handle + * this property, in which case the property is passed on on the + * interceptor in the chain, finally ending up at the built-in + * configuration handler. + */ +typedef rd_kafka_conf_res_t +(rd_kafka_interceptor_f_on_conf_set_t) (rd_kafka_conf_t *conf, + const char *name, const char *val, + char *errstr, size_t errstr_size, + void *ic_opaque); + + +/** + * @brief on_conf_dup() is called from rd_kafka_conf_dup() in the + * order the interceptors were added and is used to let + * an interceptor re-register its conf interecptors with a new + * opaque value. + * The on_conf_dup() method is called prior to the configuration from + * \p old_conf being copied to \p new_conf. + * + * @param ic_opaque The interceptor's opaque pointer specified in ..add..(). + * + * @returns RD_KAFKA_RESP_ERR_NO_ERROR on success or an error code + * on failure (which is logged but otherwise ignored). + * + * @remark No on_conf_* interceptors are copied to the new configuration + * object on rd_kafka_conf_dup(). + */ +typedef rd_kafka_resp_err_t +(rd_kafka_interceptor_f_on_conf_dup_t) (rd_kafka_conf_t *new_conf, + const rd_kafka_conf_t *old_conf, + size_t filter_cnt, + const char **filter, + void *ic_opaque); + + +/** + * @brief on_conf_destroy() is called from rd_kafka_*_conf_destroy() in the + * order the interceptors were added. + * + * @param ic_opaque The interceptor's opaque pointer specified in ..add..(). + */ +typedef rd_kafka_resp_err_t +(rd_kafka_interceptor_f_on_conf_destroy_t) (void *ic_opaque); + + +/** + * @brief on_new() is called from rd_kafka_new() prior toreturning + * the newly created client instance to the application. + * + * @param rk The client instance. + * @param conf The client instance's final configuration. + * @param ic_opaque The interceptor's opaque pointer specified in ..add..(). + * @param errstr A human readable error string in case the interceptor fails. + * @param errstr_size Maximum space (including \0) in \p errstr. + * + * @returns an error code on failure, the error is logged but otherwise ignored. + * + * @warning The \p rk client instance will not be fully set up when this + * interceptor is called and the interceptor MUST NOT call any + * other rk-specific APIs than rd_kafka_interceptor_add..(). + * + */ +typedef rd_kafka_resp_err_t +(rd_kafka_interceptor_f_on_new_t) (rd_kafka_t *rk, const rd_kafka_conf_t *conf, + void *ic_opaque, + char *errstr, size_t errstr_size); + + +/** + * @brief on_destroy() is called from rd_kafka_destroy() or (rd_kafka_new() + * if rd_kafka_new() fails during initialization). + * + * @param rk The client instance. + * @param ic_opaque The interceptor's opaque pointer specified in ..add..(). + */ +typedef rd_kafka_resp_err_t +(rd_kafka_interceptor_f_on_destroy_t) (rd_kafka_t *rk, void *ic_opaque); + + + + +/** + * @brief on_send() is called from rd_kafka_produce*() (et.al) prior to + * the partitioner being called. + * + * @param rk The client instance. + * @param rkmessage The message being produced. Immutable. + * @param ic_opaque The interceptor's opaque pointer specified in ..add..(). + * + * @remark This interceptor is only used by producer instances. + * + * @remark The \p rkmessage object is NOT mutable and MUST NOT be modified + * by the interceptor. + * + * @remark If the partitioner fails or an unknown partition was specified, + * the on_acknowledgement() interceptor chain will be called from + * within the rd_kafka_produce*() call to maintain send-acknowledgement + * symmetry. + * + * @returns an error code on failure, the error is logged but otherwise ignored. + */ +typedef rd_kafka_resp_err_t +(rd_kafka_interceptor_f_on_send_t) (rd_kafka_t *rk, + rd_kafka_message_t *rkmessage, + void *ic_opaque); + +/** + * @brief on_acknowledgement() is called to inform interceptors that a message + * was succesfully delivered or permanently failed delivery. + * The interceptor chain is called from internal librdkafka background + * threads, or rd_kafka_produce*() if the partitioner failed. + * + * @param rk The client instance. + * @param rkmessage The message being produced. Immutable. + * @param ic_opaque The interceptor's opaque pointer specified in ..add..(). + * + * @remark This interceptor is only used by producer instances. + * + * @remark The \p rkmessage object is NOT mutable and MUST NOT be modified + * by the interceptor. + * + * @warning The on_acknowledgement() method may be called from internal + * librdkafka threads. An on_acknowledgement() interceptor MUST NOT + * call any librdkafka API's associated with the \p rk, or perform + * any blocking or prolonged work. + * + * @returns an error code on failure, the error is logged but otherwise ignored. + */ +typedef rd_kafka_resp_err_t +(rd_kafka_interceptor_f_on_acknowledgement_t) (rd_kafka_t *rk, + rd_kafka_message_t *rkmessage, + void *ic_opaque); + + +/** + * @brief on_consume() is called just prior to passing the message to the + * application in rd_kafka_consumer_poll(), rd_kafka_consume*(), + * the event interface, etc. + * + * @param rk The client instance. + * @param rkmessage The message being consumed. Immutable. + * @param ic_opaque The interceptor's opaque pointer specified in ..add..(). + * + * @remark This interceptor is only used by consumer instances. + * + * @remark The \p rkmessage object is NOT mutable and MUST NOT be modified + * by the interceptor. + * + * @returns an error code on failure, the error is logged but otherwise ignored. + */ +typedef rd_kafka_resp_err_t +(rd_kafka_interceptor_f_on_consume_t) (rd_kafka_t *rk, + rd_kafka_message_t *rkmessage, + void *ic_opaque); + +/** + * @brief on_commit() is called on completed or failed offset commit. + * It is called from internal librdkafka threads. + * + * @param rk The client instance. + * @param offsets List of topic+partition+offset+error that were committed. + * The error message of each partition should be checked for + * error. + * @param ic_opaque The interceptor's opaque pointer specified in ..add..(). + * + * @remark This interceptor is only used by consumer instances. + * + * @warning The on_commit() interceptor is called from internal + * librdkafka threads. An on_commit() interceptor MUST NOT + * call any librdkafka API's associated with the \p rk, or perform + * any blocking or prolonged work. + * + * + * @returns an error code on failure, the error is logged but otherwise ignored. + */ +typedef rd_kafka_resp_err_t +(rd_kafka_interceptor_f_on_commit_t) ( + rd_kafka_t *rk, + const rd_kafka_topic_partition_list_t *offsets, + rd_kafka_resp_err_t err, void *ic_opaque); + + +/** + * @brief on_request_sent() is called when a request has been fully written + * to a broker TCP connections socket. + * + * @param rk The client instance. + * @param sockfd Socket file descriptor. + * @param brokername Broker request is being sent to. + * @param brokerid Broker request is being sent to. + * @param ApiKey Kafka protocol request type. + * @param ApiVersion Kafka protocol request type version. + * @param Corrid Kafka protocol request correlation id. + * @param size Size of request. + * @param ic_opaque The interceptor's opaque pointer specified in ..add..(). + * + * @warning The on_request_sent() interceptor is called from internal + * librdkafka broker threads. An on_request_sent() interceptor MUST NOT + * call any librdkafka API's associated with the \p rk, or perform + * any blocking or prolonged work. + * + * @returns an error code on failure, the error is logged but otherwise ignored. + */ +typedef rd_kafka_resp_err_t +(rd_kafka_interceptor_f_on_request_sent_t) ( + rd_kafka_t *rk, + int sockfd, + const char *brokername, + int32_t brokerid, + int16_t ApiKey, + int16_t ApiVersion, + int32_t CorrId, + size_t size, + void *ic_opaque); + + + +/** + * @brief Append an on_conf_set() interceptor. + * + * @param conf Configuration object. + * @param ic_name Interceptor name, used in logging. + * @param on_conf_set Function pointer. + * @param ic_opaque Opaque value that will be passed to the function. + * + * @returns RD_KAFKA_RESP_ERR_NO_ERROR on success or RD_KAFKA_RESP_ERR__CONFLICT + * if an existing intercepted with the same \p ic_name and function + * has already been added to \p conf. + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_conf_interceptor_add_on_conf_set ( + rd_kafka_conf_t *conf, const char *ic_name, + rd_kafka_interceptor_f_on_conf_set_t *on_conf_set, + void *ic_opaque); + + +/** + * @brief Append an on_conf_dup() interceptor. + * + * @param conf Configuration object. + * @param ic_name Interceptor name, used in logging. + * @param on_conf_dup Function pointer. + * @param ic_opaque Opaque value that will be passed to the function. + * + * @returns RD_KAFKA_RESP_ERR_NO_ERROR on success or RD_KAFKA_RESP_ERR__CONFLICT + * if an existing intercepted with the same \p ic_name and function + * has already been added to \p conf. + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_conf_interceptor_add_on_conf_dup ( + rd_kafka_conf_t *conf, const char *ic_name, + rd_kafka_interceptor_f_on_conf_dup_t *on_conf_dup, + void *ic_opaque); + +/** + * @brief Append an on_conf_destroy() interceptor. + * + * @param conf Configuration object. + * @param ic_name Interceptor name, used in logging. + * @param on_conf_destroy Function pointer. + * @param ic_opaque Opaque value that will be passed to the function. + * + * @returns RD_KAFKA_RESP_ERR_NO_ERROR + * + * @remark Multiple on_conf_destroy() interceptors are allowed to be added + * to the same configuration object. + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_conf_interceptor_add_on_conf_destroy ( + rd_kafka_conf_t *conf, const char *ic_name, + rd_kafka_interceptor_f_on_conf_destroy_t *on_conf_destroy, + void *ic_opaque); + + +/** + * @brief Append an on_new() interceptor. + * + * @param conf Configuration object. + * @param ic_name Interceptor name, used in logging. + * @param on_send Function pointer. + * @param ic_opaque Opaque value that will be passed to the function. + * + * @remark Since the on_new() interceptor is added to the configuration object + * it may be copied by rd_kafka_conf_dup(). + * An interceptor implementation must thus be able to handle + * the same interceptor,ic_opaque tuple to be used by multiple + * client instances. + * + * @remark An interceptor plugin should check the return value to make sure it + * has not already been added. + * + * @returns RD_KAFKA_RESP_ERR_NO_ERROR on success or RD_KAFKA_RESP_ERR__CONFLICT + * if an existing intercepted with the same \p ic_name and function + * has already been added to \p conf. + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_conf_interceptor_add_on_new ( + rd_kafka_conf_t *conf, const char *ic_name, + rd_kafka_interceptor_f_on_new_t *on_new, + void *ic_opaque); + + + +/** + * @brief Append an on_destroy() interceptor. + * + * @param rk Client instance. + * @param ic_name Interceptor name, used in logging. + * @param on_destroy Function pointer. + * @param ic_opaque Opaque value that will be passed to the function. + * + * @returns RD_KAFKA_RESP_ERR_NO_ERROR on success or RD_KAFKA_RESP_ERR__CONFLICT + * if an existing intercepted with the same \p ic_name and function + * has already been added to \p conf. + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_interceptor_add_on_destroy ( + rd_kafka_t *rk, const char *ic_name, + rd_kafka_interceptor_f_on_destroy_t *on_destroy, + void *ic_opaque); + + +/** + * @brief Append an on_send() interceptor. + * + * @param rk Client instance. + * @param ic_name Interceptor name, used in logging. + * @param on_send Function pointer. + * @param ic_opaque Opaque value that will be passed to the function. + * + * @returns RD_KAFKA_RESP_ERR_NO_ERROR on success or RD_KAFKA_RESP_ERR__CONFLICT + * if an existing intercepted with the same \p ic_name and function + * has already been added to \p conf. + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_interceptor_add_on_send ( + rd_kafka_t *rk, const char *ic_name, + rd_kafka_interceptor_f_on_send_t *on_send, + void *ic_opaque); + +/** + * @brief Append an on_acknowledgement() interceptor. + * + * @param rk Client instance. + * @param ic_name Interceptor name, used in logging. + * @param on_acknowledgement Function pointer. + * @param ic_opaque Opaque value that will be passed to the function. + * + * @returns RD_KAFKA_RESP_ERR_NO_ERROR on success or RD_KAFKA_RESP_ERR__CONFLICT + * if an existing intercepted with the same \p ic_name and function + * has already been added to \p conf. + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_interceptor_add_on_acknowledgement ( + rd_kafka_t *rk, const char *ic_name, + rd_kafka_interceptor_f_on_acknowledgement_t *on_acknowledgement, + void *ic_opaque); + + +/** + * @brief Append an on_consume() interceptor. + * + * @param rk Client instance. + * @param ic_name Interceptor name, used in logging. + * @param on_consume Function pointer. + * @param ic_opaque Opaque value that will be passed to the function. + * + * @returns RD_KAFKA_RESP_ERR_NO_ERROR on success or RD_KAFKA_RESP_ERR__CONFLICT + * if an existing intercepted with the same \p ic_name and function + * has already been added to \p conf. + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_interceptor_add_on_consume ( + rd_kafka_t *rk, const char *ic_name, + rd_kafka_interceptor_f_on_consume_t *on_consume, + void *ic_opaque); + + +/** + * @brief Append an on_commit() interceptor. + * + * @param rk Client instance. + * @param ic_name Interceptor name, used in logging. + * @param on_commit() Function pointer. + * @param ic_opaque Opaque value that will be passed to the function. + * + * @returns RD_KAFKA_RESP_ERR_NO_ERROR on success or RD_KAFKA_RESP_ERR__CONFLICT + * if an existing intercepted with the same \p ic_name and function + * has already been added to \p conf. + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_interceptor_add_on_commit ( + rd_kafka_t *rk, const char *ic_name, + rd_kafka_interceptor_f_on_commit_t *on_commit, + void *ic_opaque); + + +/** + * @brief Append an on_request_sent() interceptor. + * + * @param rk Client instance. + * @param ic_name Interceptor name, used in logging. + * @param on_request_sent() Function pointer. + * @param ic_opaque Opaque value that will be passed to the function. + * + * @returns RD_KAFKA_RESP_ERR_NO_ERROR on success or RD_KAFKA_RESP_ERR__CONFLICT + * if an existing intercepted with the same \p ic_name and function + * has already been added to \p conf. + */ +RD_EXPORT rd_kafka_resp_err_t +rd_kafka_interceptor_add_on_request_sent ( + rd_kafka_t *rk, const char *ic_name, + rd_kafka_interceptor_f_on_request_sent_t *on_request_sent, + void *ic_opaque); + + + + +/**@}*/ + + +#ifdef __cplusplus +} +#endif diff --git a/src/include/object_store_client.h b/src/include/object_store_client.h new file mode 100644 index 0000000..e6fdfda --- /dev/null +++ b/src/include/object_store_client.h @@ -0,0 +1,53 @@ +#ifndef __OBJECT_STORE_CLIENT_H__ +#define __OBJECT_STORE_CLIENT_H__ + +#include <event2/event.h> +#include <event.h> + +#include "cache_evbase_client.h" + +struct object_store_instance +{ + struct cache_evbase_instance **instances; + u_int32_t instance_num; +}; + +/*����API�̰߳�ȫ��API��ʹ��˵���ο�tango_cache_client.h*/ + +enum CACHE_ERR_CODE object_store_get_last_error(const struct cache_evbase_ctx *ctx_asyn); +long long object_store_maximum_session(const struct object_store_instance *instance); +void object_store_get_statistics(const struct object_store_instance *instance, struct cache_statistics *out); + +void object_store_global_init(void); + +/*����ʵ�����̰߳�ȫ���ڲ�������һ���߳�*/ +struct object_store_instance *object_store_instance_new(const char* profile_path, const char* section, int thread_num, void *runtimelog); + + +//GET�ӿڣ��ɹ�����0��ʧ�ܷ���-1��future�ص���������������߳���ִ�У���ͬ +int object_store_fetch_object(struct object_store_instance *instance, struct future* f, struct tango_cache_meta_get *meta, enum OBJECT_LOCATION where_to_get); +int object_store_head_object(struct object_store_instance *instance, struct future* f, struct tango_cache_meta_get *meta); +struct tango_cache_result *object_store_read_result(void *promise_result); + +//DELETE�ӿ� +int object_store_delete_object(struct object_store_instance *instance, struct future* f, const char *objkey, const char *minio_addr=NULL, const char *bucket=NULL); + +//һ�����ϴ��ӿ� +int object_store_upload_once_data(struct object_store_instance *instance, struct future* f, + enum PUT_MEMORY_COPY_WAY way, const char *data, size_t size, + struct tango_cache_meta_put *meta, + char *path/*OUT*/, size_t pathsize); +int object_store_upload_once_evbuf(struct object_store_instance *instance, struct future* f, + struct evbuffer *evbuf, + struct tango_cache_meta_put *meta, + char *path/*OUT*/, size_t pathsize); + +//��ʽ�ϴ��ӿ� +struct cache_evbase_ctx *object_store_update_start(struct object_store_instance *instance, struct future* f, struct tango_cache_meta_put *meta); +int object_store_update_frag_data(struct cache_evbase_ctx *ctx_asyn, enum PUT_MEMORY_COPY_WAY way, const char *data, size_t size); +int object_store_update_frag_evbuf(struct cache_evbase_ctx *ctx_asyn, struct evbuffer *evbuf); +int object_store_update_end(struct cache_evbase_ctx *ctx_asyn, char *path/*OUT*/, size_t pathsize); +void object_store_update_cancel(struct cache_evbase_ctx *ctx_asyn); + +#endif + diff --git a/src/include/tango_cache_client.h b/src/include/tango_cache_client.h new file mode 100644 index 0000000..07e43f2 --- /dev/null +++ b/src/include/tango_cache_client.h @@ -0,0 +1,178 @@ +#ifndef __TANGO_CACHE_CLIENT_H__ +#define __TANGO_CACHE_CLIENT_H__ + +#include <event2/event.h> +#include <event.h> + +#include <tfe_future.h> +#include "tango_cache_pending.h" + +#define USER_TAG_MAX_LEN 1518 + +enum CACHE_ERR_CODE +{ + CACHE_OK=0, + CACHE_CACHE_MISS = -101, //����δ���� + CACHE_TIMEOUT = -102, //���泬ʱ + CACHE_OUTOF_MEMORY= -103,//��ǰ�ڴ�ռ�ó������ƣ��鿴MAX_USED_MEMORY_SIZE_MB�Ƿ��С���ߵ�ǰ�ϴ����ʸ����ϵ����ߵ����� + CACHE_ERR_CURL = -104, + CACHE_ERR_WIREDLB = -105, + CACHE_ERR_SOCKPAIR= -106, + CACHE_ERR_INTERNAL= -107, + CACHE_ERR_REDIS_JSON = -108, + CACHE_ERR_REDIS_CONNECT= -109, + CACHE_ERR_REDIS_EXEC = -110, + CACHE_OUTOF_SESSION = -111, + CACHE_ERR_EVBUFFER = -112, + CACHE_UPDATE_CANCELED = -113, + CACHE_ERR_INSTANCE_ID = -114, +}; + +struct cache_statistics +{ + long long get_recv_num; //����GET�Ĵ��� + long long get_succ_http; //GET minio�ɹ��Ĵ��� + long long get_succ_redis;//GET redis�ɹ��Ĵ��� + long long get_miss_num; //GETδ���еĴ��� + long long get_err_http; //GET minioʧ�ܵĴ��� + long long get_err_redis; //GET redisʧ�ܵĴ��� + long long put_recv_num; //����UPLOAD�Ĵ��� + long long put_succ_http; //UPLOAD minio�ɹ��Ĵ��� + long long put_succ_redis;//UPLOAD redis�ɹ��Ĵ��� + long long put_err_http; //UPLOAD minioʧ�ܵĴ��� + long long put_err_redis; //UPLOAD redisʧ�ܵĴ��� + long long put_cancel; //UPLOAD Cancel���� + long long put_losf_num; //LOSF�ϲ���ĸ��� + long long del_recv_num; //����DELETE�Ĵ��� + long long del_succ_num; //DELETE�ɹ��Ĵ��� + long long del_error_num; //DELETEʧ�ܵĴ��� + long long totaldrop_num; //�ڴ����Լ�WiredLB����ʱDROP�Ĵ��� + long long memory_used; //��ǰUPLOAD BODY��ռ�ڴ��С + long long session_http; //��ǰ���ڽ���GET/PUT��HTTP�Ự�� + long long session_redis; //��ǰ���ڽ���GET/PUT��redis�Ự�� +}; + + +struct tango_cache_parameter; +struct tango_cache_instance; +struct tango_cache_ctx; + +enum CACHE_ERR_CODE tango_cache_get_last_error(const struct tango_cache_ctx *ctx); +enum CACHE_ERR_CODE tango_cache_ctx_error(const struct tango_cache_instance *instance); +long long tango_cache_maximum_session(const struct tango_cache_instance *instance); +void tango_cache_get_statistics(const struct tango_cache_instance *instance, struct cache_statistics *out); + +/*ÿ������ִ��һ�γ�ʼ��*/ +void tango_cache_global_init(void); + +//ÿ��minio��Ⱥ��bucket����һ��parameter�����instance�ɹ���һ��parameter +struct tango_cache_parameter *tango_cache_parameter_new(const char* profile_path, const char* section, void *runtimelog); +/*��������API�̲߳���ȫ*/ +//ÿ�������̴߳���һ��instance +struct tango_cache_instance *tango_cache_instance_new(struct tango_cache_parameter *param, struct event_base* evbase, void *runtimelog); + + +/****************************************** GET�ӿڵ�API ******************************************/ +enum CACHE_RESULT_TYPE +{ + RESULT_TYPE_HEADER=0, //���ֻ����һ�� + RESULT_TYPE_USERTAG, //���ֻ����һ�� + RESULT_TYPE_BODY, //���ܵ��ö�� + RESULT_TYPE_END, //ȫ��������ֻ����һ�Σ����������� + RESULT_TYPE_MISS, //����δ���У����������ͻ��⣬ֻ����һ��(��END֮��)������������ +}; + +enum OBJECT_LOCATION +{ + OBJECT_IN_UNKNOWN=0, + OBJECT_IN_MINIO, + OBJECT_IN_REDIS +}; + +struct tango_cache_meta_get +{ + const char* url; //����:URL���ǽṹ����־:�ļ�·������CACHE_OBJECT_KEY_HASH_SWITCH=0ʱ���256�ֽڣ�=1ʱ������ + struct request_freshness get; +}; + +//promise_success�Ľ��result +struct tango_cache_result +{ + const char *data_frag; //���typeΪRESULT_TYPE_HEADER��ÿ��ͷ��������һ������(HTTP1.1��ʽ) + size_t size; + size_t tlength; //������ܳ��ȣ��ص�ʱ����Ч + enum CACHE_RESULT_TYPE type; + enum OBJECT_LOCATION location; +}; + +//�ɹ�ʱ�ص�promise_success +//ʧ��ʱ�ص�promise_failed(��һ��)��ʹ��get_last_error��ȡ�����룻 +//future������ΪNULL +int tango_cache_fetch_object(struct tango_cache_instance *instance, struct future* f, struct tango_cache_meta_get *meta, enum OBJECT_LOCATION where_to_get); +int tango_cache_head_object(struct tango_cache_instance *instance, struct future* f, struct tango_cache_meta_get *meta); +//��promise_success��result������ȡ��� +struct tango_cache_result *tango_cache_read_result(future_result_t *promise_result); + + +/****************************************** DELETE�ӿڵ�API ******************************************/ +int tango_cache_delete_object(struct tango_cache_instance *instance, struct future* f, const char *objkey, const char *minio_addr=NULL, const char *bucket=NULL); + + +/****************************************** UPLOAD�ӿڵ�API ******************************************/ +/* ע��: ��future��ΪNULL�������ϴ�����ʱ�����֪ͨ�ص������������ã�*/ + +enum PUT_MEMORY_COPY_WAY +{ + PUT_MEM_COPY=0, //��������ڴ� + PUT_MEM_FREE, //�������ڴ棬��������ɱ�����ģ���ͷŸ��ڴ� +}; +enum EVBUFFER_COPY_WAY +{ + EVBUFFER_MOVE=0,//evbuffer_add_buffer + EVBUFFER_COPY, //evbuffer_add_buffer_reference +}; + +enum CACHE_HTTP_HDR_TYPE +{ + HDR_CONTENT_TYPE=0, + HDR_CONTENT_ENCODING, + HDR_CONTENT_DISPOSITION, + HDR_CONTENT_MD5, + + HDR_CONTENT_NUM, +}; + +struct tango_cache_meta_put +{ + const char* url; + const char* std_hdr[HDR_CONTENT_NUM]; //����ͷ������"Content-Type: text/html"����Ҫ�������У�NULL��ʾû�и�ͷ���� + const char* usertag; //�������������ݣ�GETʱ��ԭ������ + size_t usertag_len; //���USER_TAG_MAX_LEN��0��ʾû�и�ͷ�� + struct response_freshness put; +}; + +/****************************************** ����һ��UPLOAD�ӿڵ�API ******************************************/ +//��path��Ϊ�գ����������Ĵ洢·�� +//����ֵ: 0-�ɹ���<0ʧ�ܣ���ͬ +int tango_cache_upload_once_data(struct tango_cache_instance *instance, struct future* f, + enum PUT_MEMORY_COPY_WAY way, const char *data, size_t size, + struct tango_cache_meta_put *meta, + char *path/*OUT*/, size_t pathsize); +int tango_cache_upload_once_evbuf(struct tango_cache_instance *instance, struct future* f, + enum EVBUFFER_COPY_WAY way, struct evbuffer *evbuf, + struct tango_cache_meta_put *meta, + char *path/*OUT*/, size_t pathsize); + +/****************************************** ��ʽUPLOAD�ӿڵ�API ******************************************/ +//����ֵ: ��ΪNULL���ʾ����ʧ�ܣ�����tango_cache_ctx_error�鿴�������Ƿ���CACHE_OUTOF_MEMORY(�����������)�� +struct tango_cache_ctx *tango_cache_update_start(struct tango_cache_instance *instance, struct future* f, struct tango_cache_meta_put *meta); +//����ֵ: 0-�ɹ���<0ʧ�ܣ�����tango_cache_get_last_error�鿴�����룻 +int tango_cache_update_frag_data(struct tango_cache_ctx *ctx, const char *data, size_t size); +int tango_cache_update_frag_evbuf(struct tango_cache_ctx *ctx, enum EVBUFFER_COPY_WAY way, struct evbuffer *evbuf); +//ע��: ����ʧ��ʱ���ٵ���promise�ص�������path��ΪNULLʱ���ش洢·�� +int tango_cache_update_end(struct tango_cache_ctx *ctx, char *path/*OUT*/, size_t pathsize); +//����cancel���������ص�����������ʧ�� +void tango_cache_update_cancel(struct tango_cache_ctx *ctx); + +#endif + diff --git a/src/include/tango_cache_pending.h b/src/include/tango_cache_pending.h new file mode 100644 index 0000000..a8d5858 --- /dev/null +++ b/src/include/tango_cache_pending.h @@ -0,0 +1,97 @@ +#pragma once + +#include<time.h> + +enum tfe_http_std_field +{ + TFE_HTTP_UNKNOWN_FIELD = 0, + TFE_HTTP_HOST, + TFE_HTTP_REFERER, + TFE_HTTP_USER_AGENT, + TFE_HTTP_COOKIE, + TFE_HTTP_PROXY_AUTHORIZATION, + TFE_HTTP_AUTHORIZATION, + TFE_HTTP_LOCATION, + TFE_HTTP_SERVER, + TFE_HTTP_ETAG, + TFE_HTTP_DATE, + TFE_HTTP_TRAILER, + TFE_HTTP_TRANSFER_ENCODING, + TFE_HTTP_VIA, + TFE_HTTP_PRAGMA, + TFE_HTTP_CONNECTION, + TFE_HTTP_CONT_ENCODING, + TFE_HTTP_CONT_LANGUAGE, + TFE_HTTP_CONT_LOCATION, + TFE_HTTP_CONT_RANGE, + TFE_HTTP_CONT_LENGTH, + TFE_HTTP_CONT_TYPE, + TFE_HTTP_CONT_DISPOSITION, + TFE_HTTP_EXPIRES, + TFE_HTTP_ACCEPT_ENCODING, + TFE_HTTP_CACHE_CONTROL, + TLF_HTTP_IF_MATCH, + TLF_HTTP_IF_NONE_MATCH, + TLF_HTTP_IF_MODIFIED_SINCE, + TLF_HTTP_IF_UNMODIFIED_SINCE, + TLF_HTTP_LAST_MODIFIED +}; + + +enum cache_pending_action { + UNDEFINED = 0, + ALLOWED, + FORBIDDEN, + VERIFY +}; + + +struct tfe_http_field { + + enum tfe_http_std_field http_field; + const char* value; +}; + + +struct request_freshness { + time_t min_fresh; + time_t max_age; +}; + + +struct response_freshness{ + time_t date; + time_t last_modified; + time_t timeout; +}; + +/* +函数功能: +根据请求头字段判断是否允许将缓存作为该请求的响应,并且将请求字段对缓存新鲜度的约束范围作为传出参数返回给调用者 +参数: +request:HTTP请求字段信息,包括Pragma,Cache-Control,If-Match,If-None-Match,If-Modified-Since,If-Unmodified-Since字段 +n_fields:request包含的HTTP请求字段数目 +restrict:如果该函数返回值为ALLOWED,则返回请求Cache-Control字段包括的min-fresh或者max-age值;否则返回值为0 +返回值: +UNDEFINED = 0,//请求字段中未定义缓存的行为 +ALLOWED ,//允许使用缓存作为该请求的响应 +FORBIDDEN,//禁止使用缓存作为该请求的响应,需要向源服务器请求 +VERIFY,//禁止使用未验证有效性的缓存作为该请求的响应 +*/ +enum cache_pending_action tfe_cache_get_pending(const struct tfe_http_field *request, size_t n_fields,struct request_freshness* restrict); + + + +/* +函数功能: +根据响应字段判断该响应是否允许被缓存,并且将响应的新鲜度、date或者last-modified值作为传出参数返回给调用者 +参数: +response:HTTP响应字段信息,包括Pragma,Cache-Control,Expires、Date、Last-Modified字段 +n_fields:response包含的HTTP响应字段数目 +freshness:如果该函数返回值为ALLOWED,则返回响应Cache-Control字段的s-maxage/max-age值以及Date字段、Last-Modified字段相对时间 +返回值: +UNDEFINED = 0,//响应字段中未定义缓存的行为 +ALLOWED ,//允许缓存该响应 +FORBIDDEN,//禁止缓存该响应 +*/ +enum cache_pending_action tfe_cache_put_pending(const struct tfe_http_field *response, size_t n_fields, struct response_freshness* freshness);
\ No newline at end of file diff --git a/src/include/tfe_future.h b/src/include/tfe_future.h new file mode 100644 index 0000000..fc2311d --- /dev/null +++ b/src/include/tfe_future.h @@ -0,0 +1,28 @@ +#pragma once + +enum e_future_error +{ + FUTURE_ERROR_CANCEL, + FUTURE_ERROR_EXCEPTION, + FUTURE_ERROR_TIMEOUT +}; + +struct promise; +struct future; +typedef void future_result_t; +typedef void (future_success_cb)(future_result_t* result, void * user); +typedef void (future_failed_cb)(enum e_future_error err, const char * what, void * user); +typedef void (promise_ctx_destroy_cb)(struct promise * p); + +struct future * future_create(future_success_cb * cb_success, future_failed_cb * cb_failed, void * user); +struct future * promise_to_future(struct promise * p); +struct promise * future_to_promise(struct future * f); + +void future_destroy(struct future * f); +void promise_failed(struct promise * p, enum e_future_error error, const char * what); +void promise_success(struct promise * p, void * result); +void promise_finish(struct promise * p); +void promise_allow_many_successes(struct promise *p); +void promise_set_ctx(struct promise * p, void * ctx, promise_ctx_destroy_cb * cb); +void * promise_get_ctx(struct promise * p); +void * promise_dettach_ctx(struct promise * p); diff --git a/src/libs/libcjson.a b/src/libs/libcjson.a Binary files differnew file mode 100644 index 0000000..9a96805 --- /dev/null +++ b/src/libs/libcjson.a diff --git a/src/libs/libcrypto.a b/src/libs/libcrypto.a Binary files differnew file mode 100644 index 0000000..fddaa22 --- /dev/null +++ b/src/libs/libcrypto.a diff --git a/src/libs/libcurl.a b/src/libs/libcurl.a Binary files differnew file mode 100644 index 0000000..1d15f69 --- /dev/null +++ b/src/libs/libcurl.a diff --git a/src/libs/libevent.a b/src/libs/libevent.a Binary files differnew file mode 100644 index 0000000..1d87211 --- /dev/null +++ b/src/libs/libevent.a diff --git a/src/libs/libhiredis_vip.a b/src/libs/libhiredis_vip.a Binary files differnew file mode 100644 index 0000000..ce86d90 --- /dev/null +++ b/src/libs/libhiredis_vip.a diff --git a/src/libs/libssl.a b/src/libs/libssl.a Binary files differnew file mode 100644 index 0000000..a90a427 --- /dev/null +++ b/src/libs/libssl.a diff --git a/src/libs/libtango_cache_client.a b/src/libs/libtango_cache_client.a Binary files differnew file mode 100644 index 0000000..6454c11 --- /dev/null +++ b/src/libs/libtango_cache_client.a diff --git a/src/libs/libxml2.a b/src/libs/libxml2.a Binary files differnew file mode 100644 index 0000000..915036d --- /dev/null +++ b/src/libs/libxml2.a diff --git a/src/objectscanner_analyze.cpp b/src/objectscanner_analyze.cpp new file mode 100644 index 0000000..dccca63 --- /dev/null +++ b/src/objectscanner_analyze.cpp @@ -0,0 +1,275 @@ +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include <errno.h> +#include <sys/prctl.h> +#include <string.h> + +#include "librdkafka/rdkafka.h" + +#include "avlsdk/engine.h" +#include "avlsdk/error_code.h" +#include "avlsdk/AVLSDK_rpt_idx.h" +#include "avlsdk/AVLSDK_conf_idx.h" +#include "avlsdk/ID2Name_interface.h" + +#include "object_store_client.h" + +#include "objectscanner_main.h" +#include "objectscanner_kafka.h" +#include "objectscanner_analyze.h" + +extern objscan_global_info_t g_objscan_info; + +int avl_scan_engine_init(void) +{ + long ret, long_last_ret; + void *p_engine_handle=NULL, *p_i2n_handle=NULL; + void *p_sdk_handle = NULL, *p_name_handle = NULL; + + ret = AVL_SDK_CreateInstance(&p_engine_handle); + if(ret != ERR_SUCCESS) + { + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "AVL_SDK_CreateInstance error: %ld", ret); + return -1; + } + ret = AVL_SDK_LoadConfigFile(p_engine_handle, (char *)DEFAULT_CONFIG_FILE); + if(ret != ERR_SUCCESS) + { + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "AVL_SDK_LoadConfigFile error: %ld", ret); + return -1; + } + ret = AVL_SDK_SetConfigInt(p_engine_handle, CFG_INT_APACK_RECURE_LAYER, 5); + if(ret != ERR_SUCCESS) + { + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "AVL_SDK_SetConfigInt error: %ld", ret); + return -1; + } + ret = AVL_SDK_SetConfigString(p_engine_handle, CFG_STR_LICENSE_PATH, DEFAULT_LICENCE_FILE); + if(ret != ERR_SUCCESS) + { + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "AVL_SDK_SetConfigString error: %ld", ret); + return -1; + } + ret = AVL_SDK_InitInstance(p_engine_handle, NULL); + if(ret != ERR_SUCCESS) + { + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "AVL_SDK_InitInstance error: %ld", ret); + return -1; + } + + ret = AVL_NTranser_Init(DEFAULT_ID2N_DB_PATH, &p_i2n_handle); + if(ret != ERR_SUCCESS) + { + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "AVL_NTranser_Init error: %ld", ret); + return -1; + } + + g_objscan_info.p_engine_handle = p_engine_handle; + g_objscan_info.p_i2n_handle = p_i2n_handle; + return 0; +} + +static long func_long_query_continue_callback(void *p_param) +{ + message_meta_item_t *message = (message_meta_item_t *)p_param; + + // This is the code sample, so it returns unconditionally. Users can modify according to the condition. + //�кܶ����ļ��������һ�����ļ�ɨ�к��ټ���ɨ�� + return (message->hitted)?OD_ABORT:OD_CONTINUE; +} + +static long func_long_get_rslt_callback(P_OBJ_PROVIDER p_op, void *p_data, void *p_param) +{ + long long_malware_id=0, long_qry_ret=-1; + message_meta_item_t *message = (message_meta_item_t *)p_param; + unsigned char *puchar_analyser=NULL, auchar_malware_name[128]={0}; + char *malware_type, *malware_name; + char *save_ptr; + + if(p_data == NULL) + { + return -1; + } + // Query the Malware ID + long_qry_ret = AVL_SDK_QueryReportInt(g_objscan_info.p_engine_handle, p_data, RPT_IDX_MALWARE_ID, &long_malware_id); + if (long_qry_ret==ERR_RPT_NOT_EXIST || long_qry_ret<0) + { + return long_qry_ret; + } + + // Query the analyser who detected this malware, users will use it when they need to get the malware name + long_qry_ret = AVL_SDK_QueryReportStr(g_objscan_info.p_engine_handle, p_data, RPT_IDX_ANALYSER, &puchar_analyser); + if (long_qry_ret != ERR_SUCCESS) + { + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "AVL_SDK_QueryReportStr error: %ld", long_qry_ret); + return long_qry_ret; + } + + // Query the VName + long_qry_ret = AVL_NTranser_QueryNameByID(g_objscan_info.p_i2n_handle, (char *)puchar_analyser, long_malware_id, (unsigned char *)auchar_malware_name, sizeof(auchar_malware_name) - 1); + if (long_qry_ret < 0) + { + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "AVL_NTranser_QueryNameByID error: %ld", long_qry_ret); + return long_qry_ret; + } + + /* AVL���к�, auchar_malware_name��ʽ�����"Trojan/Win32.SGeneric", ��Ҫ��� */ + malware_type = strtok_r((char *)auchar_malware_name, "/", &save_ptr); + malware_name = strtok_r(NULL, "/", &save_ptr); + if(NULL == malware_name) + { + malware_name = malware_type; + } + cJSON_AddNumberToObject(message->meta_json, "malware_id", long_malware_id); + cJSON_AddStringToObject(message->meta_json, "malware_type", malware_type); + cJSON_AddStringToObject(message->meta_json, "malware_name", malware_name); + message->hitted = 1; + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_DEBUG, "AVL_SDK_Scan %s hit, type: %s, name: %s", message->object_uri, malware_type, malware_name); + atomic_inc(&g_objscan_info.statistic.num[MESSAGE_HITTED]); + return long_qry_ret; +} + +static int32_t scan_object_by_avl_engine(message_meta_item_t *message) +{ + long long_last_ret = 0; + OBJ_PROVIDER op = {0}; + OBJ_DISPOSER od = {0}; + + op.obj_ver = CUR_ENGINE_VER; + op.evro_type = ET_DESKTOP; + op.buf = (unsigned char *)message->content; + op.size = message->current_len; + strncpy((char *)op.obj_des, message->object_uri, strlen(message->object_uri)); + + od.rpt_callback = func_long_get_rslt_callback; + od.p_rpt_param = message; + od.query_continue_callback = func_long_query_continue_callback; + od.p_qc_param = message; + + long_last_ret = AVL_SDK_Scan(g_objscan_info.p_engine_handle, &op, &od); + if (long_last_ret < 0) + { + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "AVL_SDK_Scan error: %ld", long_last_ret); + return 0; + } + return message->hitted; +} + +void* thread_analyze_object(void *arg) +{ + message_meta_item_t *message; + char *buffer; + size_t buflen; + long node_size; + int ret=0; + + prctl(PR_SET_NAME, "anly_object"); + while(1) + { + node_size = sizeof(message_meta_item_t *); + if(MESA_lqueue_get_head(g_objscan_info.queue_analyze, (void *)&message, &node_size)) + { + usleep(100000); + continue; + } + + if(scan_object_by_avl_engine(message)) + { + buffer = cJSON_PrintUnformatted(message->meta_json); + buflen = strlen(buffer); + ret = rd_kafka_produce(g_objscan_info.produc_topic, RD_KAFKA_PARTITION_UA, RD_KAFKA_MSG_F_FREE, buffer, buflen, NULL, 0, NULL); + rd_kafka_poll(g_objscan_info.kafka_producer, 0); + if(ret!=0) + { + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_DEBUG, "rd_kafka_produce error: %d", rd_kafka_last_error()); + atomic_inc(&g_objscan_info.statistic.num[MESSAGE_OTH_FAIL]); + free(buffer); + } + } + else + { + atomic_inc(&g_objscan_info.statistic.num[MESSAGE_SUCC]); + } + destroy_parsed_message(message); + } + return NULL; +} + +void get_future_failed(enum e_future_error err, const char * what, void * user) +{ + message_meta_item_t *message = (message_meta_item_t *)user; + + atomic_inc(&(g_objscan_info.statistic.num[MESSAGE_OTH_FAIL])); + destroy_parsed_message(message); +} + +void get_future_success(future_result_t* result, void * user) +{ + struct tango_cache_result *res = cache_evbase_read_result(result); + message_meta_item_t *message = (message_meta_item_t *)user; + + switch(res->type) + { + case RESULT_TYPE_USERTAG: + case RESULT_TYPE_HEADER: + if(message->content == NULL) + { + message->max_len = (res->tlength>=g_objscan_info.anly_max_len)?g_objscan_info.anly_max_len:res->tlength; + message->content = (char *)malloc(message->max_len); + } + break; + + case RESULT_TYPE_BODY: + if(message->current_len+res->size <= message->max_len) + { + memcpy(message->content+message->current_len, res->data_frag, res->size); + message->current_len += res->size; + } + break; + + case RESULT_TYPE_MISS: + atomic_inc(&(g_objscan_info.statistic.num[MESSAGE_NOT_EXIST])); + destroy_parsed_message(message); + break; + + case RESULT_TYPE_END: + if(MESA_lqueue_join_tail(g_objscan_info.queue_analyze, (void *)&message, sizeof(message)) < 0) + { + atomic_inc(&g_objscan_info.statistic.num[MESSAGE_DROP]); + destroy_parsed_message(message); + } + break; + default:break; + } +} + +void* thread_fetch_object(void *arg) +{ + message_meta_item_t *message; + long node_size; + struct tango_cache_meta_get getmeta; + + prctl(PR_SET_NAME, "fetch_object"); + memset(&getmeta, 0, sizeof(struct tango_cache_meta_get)); + while(1) + { + node_size = sizeof(message_meta_item_t *); + if(MESA_lqueue_get_head(g_objscan_info.queue_delay, (void *)&message, &node_size)) + { + usleep(100000); + continue; + } + + message->future = future_create(get_future_success, get_future_failed, message); + + getmeta.url = message->object_uri; + if(object_store_fetch_object(g_objscan_info.instance, message->future, &getmeta, OBJECT_IN_UNKNOWN) < 0) + { + get_future_failed(FUTURE_ERROR_CANCEL, "", message); + } + } + return NULL; +} + diff --git a/src/objectscanner_analyze.h b/src/objectscanner_analyze.h new file mode 100644 index 0000000..0b177e2 --- /dev/null +++ b/src/objectscanner_analyze.h @@ -0,0 +1,16 @@ +#ifndef __OBJECT_SCANNER_ANALYZE_H__ +#define __OBJECT_SCANNER_ANALYZE_H__ + +#define DEFAULT_SDK_PATH "./avlsdk3/AVLSDK.so" +#define DEFAULT_ID2NAME_PATH "./avlsdk3/aid2name.so" +#define DEFAULT_ID2N_DB_PATH "./avlsdk3/NData" +#define DEFAULT_CONFIG_FILE "./avlsdk3/Config/high_scan.ct" +#define DEFAULT_LICENCE_FILE "./avlsdk3/License.alf" + +int avl_scan_engine_init(void); + +void* thread_analyze_object(void *arg); +void* thread_fetch_object(void *arg); + +#endif + diff --git a/src/objectscanner_kafka.cpp b/src/objectscanner_kafka.cpp new file mode 100644 index 0000000..6b52447 --- /dev/null +++ b/src/objectscanner_kafka.cpp @@ -0,0 +1,331 @@ +#include <time.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include <errno.h> +#include <string.h> +#include <sys/prctl.h> + +#include "objectscanner_main.h" +#include "objectscanner_kafka.h" + +#define OBJSCAN_RESULT_TOPIC "NTC-HTTP-OBJSCAN-RESULT" +#define OBJSCAN_HTTP_DOC_TOPIC "NTC-COLLECT-HTTP-DOC-LOG" +#define OBJSCAN_HTTP_EXE_TOPIC "NTC-COLLECT-HTTP-EXE-LOG" + +extern objscan_global_info_t g_objscan_info; + +static void kafka_conf_log_cb(const rd_kafka_t *rk, int level, const char *fac, const char *buf) +{ + if(level <= g_objscan_info.sys_log_level) + { + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "In log_cb, %s: %s", fac, buf); + } +} + +static void kafka_conf_error_cb (rd_kafka_t *rk, int err, const char *reason, void *opaque) +{ + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "In error_cb, error: %d, reason: %s", err, reason); +} + +static void print_partition_list (const char *type, const rd_kafka_topic_partition_list_t *partitions) +{ + int i; + char buffer[2048]; + + sprintf(buffer, "Consumer group rebalanced, type: %s, ", type); + for (i = 0 ; i < partitions->cnt ; i++) + { + snprintf(buffer+strlen(buffer), 2048-strlen(buffer), "%s %s[%u] offset %lu", + i > 0 ? ",":"", partitions->elems[i].topic, partitions->elems[i].partition, partitions->elems[i].offset); + } + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "%s", buffer); + printf("%s\n", buffer); +} + +//����һ�����Ϸ���OFFSET���Ա�����µ����ݿ�ʼ���� +static void reset_kafka_offsets(rd_kafka_topic_partition_list_t *partitions) +{ + rd_kafka_resp_err_t err; + int i; + + for (i = 0 ; i < partitions->cnt ; i++) + { + err = rd_kafka_topic_partition_list_set_offset(partitions, partitions->elems[i].topic, partitions->elems[i].partition, -1); + if(err != RD_KAFKA_RESP_ERR_NO_ERROR) + { + printf("Set Kafka offset error: %s\n", rd_kafka_err2str(err)); + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "Set Kafka offset error: %s\n", rd_kafka_err2str(err)); + } + } +} + +static void kafka_rebalance_cb (rd_kafka_t *rk, rd_kafka_resp_err_t err, rd_kafka_topic_partition_list_t *partitions, void *opaque) +{ + switch (err) + { + case RD_KAFKA_RESP_ERR__ASSIGN_PARTITIONS: + print_partition_list("assigned", partitions); + if(g_objscan_info.consume_from_latest) + { + reset_kafka_offsets(partitions); + } + rd_kafka_assign(rk, partitions); + break; + + case RD_KAFKA_RESP_ERR__REVOKE_PARTITIONS: + print_partition_list("revoked", partitions); + rd_kafka_assign(rk, NULL); + break; + + default: + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "failed: %s\n", rd_kafka_err2str(err)); + rd_kafka_assign(rk, NULL); + break; + } +} + +int32_t rdkafka_consumer_init(void) +{ + char errString[512] = {0}, confbuf[128]; + rd_kafka_conf_t *config; + rd_kafka_topic_conf_t *topic_conf; + rd_kafka_topic_partition_list_t *topics; + rd_kafka_resp_err_t err; + + /*Consumer configuration*/ + config = rd_kafka_conf_new(); + rd_kafka_conf_set(config, "topic.metadata.refresh.interval.ms", "60000", errString, 512); + if(rd_kafka_conf_set(config, "group.id", g_objscan_info.kafka_consu_name, errString, 512) != RD_KAFKA_CONF_OK) + { + printf("rd_kafka_conf_set group.id error: %s.\n", errString); + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "rd_kafka_conf_set group.id error: %s.\n", errString); + return -1; + } + + /*Topic configuration*/ + topic_conf = rd_kafka_topic_conf_new(); + rd_kafka_topic_conf_set(topic_conf, "consume.callback.max.messages", confbuf, errString, 512); + rd_kafka_topic_conf_set(topic_conf, "auto.commit.enable", "true", errString, 512); + rd_kafka_topic_conf_set(topic_conf, "auto.offset.reset", "earliest", errString, 512); //RD_KAFKA_OFFSET_STORED��ʼû��offesetʱ + if(rd_kafka_topic_conf_set(topic_conf, "offset.store.method", "broker", errString, 512) != RD_KAFKA_CONF_OK) + { + printf("rd_kafka_topic_conf_set offset.store.method(broker) error: %s.\n", errString); + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "rd_kafka_topic_conf_set offset.store.method(broker) error: %s.\n", errString); + return -1; + } + rd_kafka_conf_set_default_topic_conf(config, topic_conf); + rd_kafka_conf_set_rebalance_cb(config, kafka_rebalance_cb); + rd_kafka_conf_set_log_cb(config, kafka_conf_log_cb); + rd_kafka_conf_set_error_cb(config, kafka_conf_error_cb); + + if(!(g_objscan_info.kafka_consumer = rd_kafka_new(RD_KAFKA_CONSUMER, config, errString, sizeof(errString)))) + { + printf("rd_kafka_new error: %s.\n", errString); + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "rd_kafka_new error: %s.\n", errString); + return -1; + } + + if(rd_kafka_brokers_add(g_objscan_info.kafka_consumer, g_objscan_info.kafka_brokers) == 0) + { + printf("rd_kafka_brokers_add: %s error.\n", g_objscan_info.kafka_brokers); + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "rd_kafka_brokers_add %s error.", g_objscan_info.kafka_brokers); + return -1; + } + rd_kafka_poll_set_consumer(g_objscan_info.kafka_consumer); + + topics = rd_kafka_topic_partition_list_new(2); + rd_kafka_topic_partition_list_add(topics, OBJSCAN_HTTP_DOC_TOPIC, -1); + rd_kafka_topic_partition_list_add(topics, OBJSCAN_HTTP_EXE_TOPIC, -1); + err = rd_kafka_subscribe(g_objscan_info.kafka_consumer, topics); + if(err) + { + printf("%% Failed to start consuming topics: %s\n", rd_kafka_err2str(err)); + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "Failed to start consuming topics: %s\n", rd_kafka_err2str(err)); + return -2; + } + return 0; +} + +static void produce_delivery_msg_cb(rd_kafka_t *rk, const rd_kafka_message_t *rkmessage, void *opaque) +{ + if(rkmessage->err) + { + atomic_inc(&(g_objscan_info.statistic.num[MESSAGE_OTH_FAIL])); + } + else + { + atomic_inc(&(g_objscan_info.statistic.num[MESSAGE_SUCC])); + } +} + +int32_t rdkafka_producer_init(void) +{ + char errString[512] = {0}, config_buf[128]; + rd_kafka_conf_t *config; + rd_kafka_topic_conf_t *topic_conf; + + /*Consumer configuration*/ + config = rd_kafka_conf_new(); + sprintf(config_buf, "%u", g_objscan_info.produce_q_size); + rd_kafka_conf_set(config, "queue.buffering.max.messages", config_buf, errString, sizeof(errString)); + rd_kafka_conf_set(config, "topic.metadata.refresh.interval.ms", "60000", errString, sizeof(errString)); + rd_kafka_conf_set_dr_msg_cb(config, produce_delivery_msg_cb); + + if(!(g_objscan_info.kafka_producer = rd_kafka_new(RD_KAFKA_PRODUCER, config, errString, sizeof(errString)))) + { + printf("rd_kafka_new error: %s.\n", errString); + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "rd_kafka_new error: %s.\n", errString); + return -1; + } + if(rd_kafka_brokers_add(g_objscan_info.kafka_producer, g_objscan_info.kafka_brokers) == 0) + { + printf("rd_kafka_brokers_add: %s error.\n", g_objscan_info.kafka_brokers); + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "rd_kafka_brokers_add %s error.", g_objscan_info.kafka_brokers); + return -1; + } + + /*Topic configuration*/ + sprintf(config_buf, "%u", g_objscan_info.kafka_req_ack); + topic_conf = rd_kafka_topic_conf_new(); + rd_kafka_topic_conf_set(topic_conf, "request.required.acks", config_buf, errString, 512); + g_objscan_info.produc_topic= rd_kafka_topic_new(g_objscan_info.kafka_producer, OBJSCAN_RESULT_TOPIC, topic_conf); + if(NULL==g_objscan_info.produc_topic) + { + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "create topic: %s error.", OBJSCAN_RESULT_TOPIC); + return -1; + } + return 0; +} + +void destroy_parsed_message(message_meta_item_t *message) +{ + future_destroy(message->future); + free(message->content); + + cJSON_Delete(message->meta_json); + free(message); +} + +static message_meta_item_t *parse_rkmessage_cjson(const char* data, int datalen) +{ + cJSON *root, *psub = NULL; + char *buffer = (char *)malloc(datalen+1), *pos_colon; + message_meta_item_t *message; + + memcpy(buffer, data, datalen); + buffer[datalen] = '\0'; + root = cJSON_Parse(buffer); + free(buffer); + if(NULL == root) + { + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_INFO, "recv rkmessage error: cJSON_Parse failed."); + return NULL; + } + + if(NULL==(psub=cJSON_GetObjectItem(root, "res_body_file"))) + { + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_INFO, "recv rkmessage fail: path is NULL."); + cJSON_Delete(root); + return NULL; + } + + if(psub->type!=cJSON_String || strncmp(psub->valuestring, "http://", strlen("http://")) || + NULL==(pos_colon=strchr(psub->valuestring+strlen("http://"), '/'))) + { + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_INFO, "recv rkmessage fail: message format error."); + cJSON_Delete(root); + return NULL; + } + + message = (message_meta_item_t *)calloc(1, sizeof(message_meta_item_t)); + message->meta_json = root; + snprintf(message->object_uri, 256, "%s", pos_colon+1); + + if(NULL!=(psub=cJSON_GetObjectItem(root, "found_time"))) + { + message->found_time = psub->valuedouble; + } + else + { + message->found_time = time(NULL); + } + return message; +} + +void* thread_delay_msg_queue(void *arg) +{ + message_meta_item_t *message; + long node_size; + time_t now; + + prctl(PR_SET_NAME, "queue_delay"); + + while(1) + { + node_size = sizeof(message_meta_item_t *); + if(MESA_lqueue_get_head(g_objscan_info.queue_msg, (void *)&message, &node_size)) + { + usleep(100000); + continue; + } + now = time(NULL); + if((message->found_time + g_objscan_info.delay_time_s) > now) //��֤�ӳ�g_objscan_info.delay_time_sʱ�� + { + sleep(g_objscan_info.delay_time_s - (now - message->found_time)); + } + + if(MESA_lqueue_join_tail(g_objscan_info.queue_delay, (void *)&message, sizeof(message)) < 0) + { + atomic_inc(&(g_objscan_info.statistic.num[MESSAGE_DROP])); + destroy_parsed_message(message); + } + } + return NULL; +} + +void* thread_recv_kafka_msg(void *arg) +{ + rd_kafka_message_t *rkmessage; + message_meta_item_t *parsed_msg; + int32_t ret; + + prctl(PR_SET_NAME, "kafka_rcvmsg"); + while(1) + { + rkmessage = rd_kafka_consumer_poll(g_objscan_info.kafka_consumer, g_objscan_info.consume_timeout_ms); + if(rkmessage) + { + if(rkmessage->err == RD_KAFKA_RESP_ERR_NO_ERROR) + { + if(NULL==(parsed_msg=parse_rkmessage_cjson((const char*)rkmessage->payload, rkmessage->len))) + { + atomic_inc(&(g_objscan_info.statistic.num[MESSAGE_RCV_ERROR])); + rd_kafka_message_destroy(rkmessage); + continue; + } + cJSON_AddStringToObject(parsed_msg->meta_json, "topic_name", rd_kafka_topic_name(rkmessage->rkt)); + + ret = MESA_QUEUE_RET_CANT_GET_LOCK; + while(ret==MESA_QUEUE_RET_CANT_GET_LOCK || ret==MESA_QUEUE_RET_GET_LOCK_TMOUT) + { + ret = MESA_lqueue_try_join_tail(g_objscan_info.queue_msg, (void *)&parsed_msg, sizeof(parsed_msg)); + } + if(ret < 0) + { + atomic_inc(&(g_objscan_info.statistic.num[MESSAGE_DROP])); + destroy_parsed_message(parsed_msg); + } + } + rd_kafka_message_destroy(rkmessage); + } + else + { + usleep(200000); + } + } + + return NULL; +} + diff --git a/src/objectscanner_kafka.h b/src/objectscanner_kafka.h new file mode 100644 index 0000000..0e5c9e8 --- /dev/null +++ b/src/objectscanner_kafka.h @@ -0,0 +1,48 @@ +#ifndef __OBJECT_SCANNER_KAFKA_H__ +#define __OBJECT_SCANNER_KAFKA_H__ + +#include "cJSON.h" + +#include "object_store_client.h" + +enum MESSAGE_PROC_STATE +{ + MESSAGE_SUCC=0, + MESSAGE_HITTED, + MESSAGE_RCV_ERROR, + MESSAGE_DROP, + MESSAGE_NOT_EXIST, + MESSAGE_ANLY_FAIL, + MESSAGE_OTH_FAIL, + + MESSAGE_STATE_NUM, +}; + +struct objscan_statistics +{ + long num[MESSAGE_STATE_NUM]; +}; + +typedef struct __message_meta_item +{ + cJSON *meta_json; + char object_uri[256]; + time_t found_time; + + struct future * future; + char *content; + size_t current_len; + size_t max_len; + int32_t hitted; +}message_meta_item_t; + +int32_t rdkafka_consumer_init(void); +int32_t rdkafka_producer_init(void); + +void destroy_parsed_message(message_meta_item_t *message); + +void* thread_delay_msg_queue(void *arg); +void* thread_recv_kafka_msg(void *arg); + +#endif + diff --git a/src/objectscanner_main.cpp b/src/objectscanner_main.cpp new file mode 100644 index 0000000..bf8831a --- /dev/null +++ b/src/objectscanner_main.cpp @@ -0,0 +1,338 @@ +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include <errno.h> +#include <sys/syslog.h> +#include <string.h> +#include <sys/stat.h> +#include <pthread.h> + +#include <MESA/MESA_prof_load.h> +#include <MESA/wired_cfg.h> + +#include "object_store_client.h" + +#include "objectscanner_main.h" +#include "objectscanner_analyze.h" + +objscan_global_info_t g_objscan_info; + +static int mkdir_according_path(const char * path) +{ + char buffer[256]; + const char *ps=path, *pc; + + if(*ps == '/') + ps += 1; + + while((pc = strchr(ps, '/')) != NULL) + { + while(*(pc+1) == '/') + pc++; + + memcpy(buffer, path, pc - path); + buffer[pc-path] = '\0'; + + if(access(buffer, F_OK)) + { + if(mkdir(buffer, 0777)) + { + return -1; + } + } + + ps = pc + 1; + } + if(access(path, F_OK)) + { + if(mkdir(path, 0777)) + { + return -1; + } + } + return 0; +} + +void wired_load_config(const char *conf_path) +{ + void *wired_handle = wired_cfg_create("OBJECT_SCAN_CONF", conf_path); + if(wired_cfg_init(wired_handle) != WCFG_RET_OK) + { + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "wired_cfg_init %s failed.", conf_path); + } + wired_cfg_destroy(wired_handle); +} + +static int _unfold_IP_range(char* ip_range, char***ip_list, int size) +{ + int i=0,count=0, ret=0; + int range_digits[5]; + memset(range_digits,0,sizeof(range_digits)); + ret=sscanf(ip_range,"%d.%d.%d.%d-%d",&range_digits[0],&range_digits[1],&range_digits[2],&range_digits[3],&range_digits[4]); + if(ret!=4&&ret!=5) + { + return 0; + } + if(ret==4&&range_digits[4]==0) + { + range_digits[4]=range_digits[3]; + } + for(i=0;i<5;i++) + { + if(range_digits[i]<0||range_digits[i]>255) + { + return 0; + } + } + count=range_digits[4]-range_digits[3]+1; + *ip_list=(char**)realloc(*ip_list, sizeof(char*)*(size+count)); + for(i=0;i<count;i++) + { + (*ip_list)[size+i]=(char*)malloc(64); + snprintf((*ip_list)[size+i],64,"%d.%d.%d.%d",range_digits[0],range_digits[1],range_digits[2],range_digits[3]+i); + } + return count; +} + +static int unfold_IP_range(const char* ip_range, char***ip_list) +{ + char *token=NULL,*sub_token=NULL,*saveptr; + char *buffer=(char*)calloc(sizeof(char),strlen(ip_range)+1); + int count=0; + strcpy(buffer,ip_range); + for (token = buffer; ; token= NULL) + { + sub_token= strtok_r(token,";", &saveptr); + if (sub_token == NULL) + break; + count+=_unfold_IP_range(sub_token, ip_list,count); + } + free(buffer); + return count; +} + +static int build_kafka_cluster_addrs(const char *iplist, u_int32_t port, char *brokers, size_t size, void *runtimelog) +{ + u_int32_t redis_ip_num; + char **redis_iplist=NULL; + size_t addrlen; + + redis_ip_num = unfold_IP_range(iplist, &redis_iplist); + if(redis_ip_num ==0 ) + { + MESA_HANDLE_RUNTIME_LOGV2(runtimelog, RLOG_LV_FATAL, "decode KAFKA_BROKSER_IPLIST %s failed.", iplist); + return -1; + } + + memset(brokers, 0, size); + for(u_int32_t i=0; i<redis_ip_num; i++) + { + addrlen = strlen(brokers); + snprintf(brokers+addrlen, size-addrlen, "%s:%u,", redis_iplist[i], port); + free(redis_iplist[i]); + } + addrlen = strlen(brokers); + brokers[addrlen-1] = '\0'; + free(redis_iplist); + return 0; +} + +void register_field_stat(void) +{ + int value; + const char *field_names[MESSAGE_STATE_NUM]={"SUCC", "HITTED", "RCV_ERROR", "DROP", "NOT_EXIST", "ANALYZE_FAIL", "OTH_FAIL"}; + const char *status_names[FSSTAT_ID_NUM]={"MSG_QUEUE", "DELAY_QUEUE", "ANALY_QUEUE", "KAFKA_P_Q"}; + + g_objscan_info.fsstat_handle = FS_create_handle(); + FS_set_para(g_objscan_info.fsstat_handle, OUTPUT_DEVICE, g_objscan_info.fsstat_filepath, strlen(g_objscan_info.fsstat_filepath)+1); + value = 1; + FS_set_para(g_objscan_info.fsstat_handle, PRINT_MODE, &value, sizeof(value)); + value = 2; + FS_set_para(g_objscan_info.fsstat_handle, STAT_CYCLE, &value, sizeof(value)); + value = 0; + FS_set_para(g_objscan_info.fsstat_handle, CREATE_THREAD, &value, sizeof(value)); + FS_set_para(g_objscan_info.fsstat_handle, APP_NAME, g_objscan_info.fsstat_appname, strlen(g_objscan_info.fsstat_appname)+1); + FS_set_para(g_objscan_info.fsstat_handle, STATS_SERVER_IP, g_objscan_info.fsstat_dst_ip, strlen(g_objscan_info.fsstat_dst_ip)+1); + FS_set_para(g_objscan_info.fsstat_handle, STATS_SERVER_PORT, &g_objscan_info.fsstat_dst_port, sizeof(g_objscan_info.fsstat_dst_port)); + + for(int i=0; i<MESSAGE_STATE_NUM; i++) + { + g_objscan_info.fsstat_field_ids[i] = FS_register(g_objscan_info.fsstat_handle, FS_STYLE_FIELD, FS_CALC_CURRENT, field_names[i]); + } + for(int i=0; i<FSSTAT_ID_NUM; i++) + { + g_objscan_info.fsstat_status_ids[i] = FS_register(g_objscan_info.fsstat_handle, FS_STYLE_STATUS, FS_CALC_CURRENT, status_names[i]); + } + FS_start(g_objscan_info.fsstat_handle); +} + +static int32_t read_config_and_init(const char *config_file) +{ + char tmp_buf[4096], tmp_logdir[256]; + u_int32_t kafka_port; + + memset(&g_objscan_info, 0, sizeof(objscan_global_info_t)); + + //log init// + MESA_load_profile_int_def(config_file, "OBJSCAN", "SYS_LOG_LEVEL", &g_objscan_info.sys_log_level, LOG_INFO); + MESA_load_profile_string_def(config_file, "OBJSCAN", "RUN_LOG_DIR", g_objscan_info.root_log_dir, sizeof(g_objscan_info.root_log_dir), "./log"); + MESA_load_profile_uint_def(config_file, "OBJSCAN", "RUN_LOG_LV", &g_objscan_info.log_level, 10); + sprintf(tmp_logdir, "%s/runtime_log", g_objscan_info.root_log_dir); + if(mkdir_according_path(tmp_logdir)) + { + printf("mkdir %s failed: %s\n", g_objscan_info.root_log_dir, strerror(errno)); + return -1; + } + snprintf(tmp_buf, 256, "%s/runtime.log", tmp_logdir); + g_objscan_info.log_runtime = MESA_create_runtime_log_handle(tmp_buf, g_objscan_info.log_level); + if(NULL==g_objscan_info.log_runtime) + { + printf("MESA_create_runtime_log_handle %s failed: %s\n", tmp_logdir, strerror(errno)); + return -1; + } + sprintf(tmp_logdir, "%s/log_statistic", g_objscan_info.root_log_dir); + if(mkdir_according_path(tmp_logdir)) + { + printf("mkdir %s failed: %s\n", g_objscan_info.root_log_dir, strerror(errno)); + return -1; + } + snprintf(tmp_buf, 256, "%s/statistic.log", tmp_logdir); + g_objscan_info.log_statistic = MESA_create_runtime_log_handle(tmp_buf, g_objscan_info.log_level); + if(NULL==g_objscan_info.log_statistic) + { + printf("MESA_create_runtime_log_handle %s failed: %s\n", tmp_logdir, strerror(errno)); + return -1; + } + + MESA_load_profile_uint_def(config_file, "OBJSCAN", "MAX_QUEUE_ELEMENTS", &g_objscan_info.queue_elem_size, 100000); + MESA_load_profile_uint_def(config_file, "OBJSCAN", "ANALYZE_MAX_SIZE", &g_objscan_info.anly_max_len, 1048576); + MESA_load_profile_uint_def(config_file, "OBJSCAN", "ANALYZE_THREAD_NUM", &g_objscan_info.thread_num_anly, 1); + MESA_load_profile_uint_def(config_file, "OBJSCAN", "FETCH_MINIO_THREAD_NUM", &g_objscan_info.thread_num_fetch, 1); + MESA_load_profile_uint_def(config_file, "OBJSCAN", "DELAY_ANALYZE_TIME_S", &g_objscan_info.delay_time_s, 20); + + MESA_load_profile_string_def(config_file, "OBJSCAN", "LOG_FSSTAT_APPNAME", g_objscan_info.fsstat_appname, 16, "ObjScan"); + MESA_load_profile_string_def(config_file, "OBJSCAN", "LOG_FSSTAT_FILEPATH", g_objscan_info.fsstat_filepath, 256, "./log/objscan_fsstat.log"); + MESA_load_profile_uint_def(config_file, "OBJSCAN", "LOG_FSSTAT_INTERVAL", &g_objscan_info.fsstat_period, 60); + MESA_load_profile_uint_def(config_file, "OBJSCAN", "LOG_FSSTAT_TRIG", &g_objscan_info.fsstatid_trig, 1); + MESA_load_profile_string_def(config_file, "OBJSCAN", "LOG_FSSTAT_DST_IP", g_objscan_info.fsstat_dst_ip, 64, "10.172.128.2"); + MESA_load_profile_int_def(config_file, "OBJSCAN", "LOG_FSSTAT_DST_PORT", &g_objscan_info.fsstat_dst_port, 8125); + + //KAFKA CONF// + MESA_load_profile_string_def(config_file, "OBJSCAN", "KAFKA_CONSUMER_NAME", g_objscan_info.kafka_consu_name, 128, "ObjectScanner"); + MESA_load_profile_uint_def(config_file, "OBJSCAN", "KAFKA_CONSUME_FROM_LATEST", &g_objscan_info.consume_from_latest, 0); + MESA_load_profile_uint_def(config_file, "OBJSCAN", "KAFKA_CONSUME_TIMEOUT_MS", &g_objscan_info.consume_timeout_ms, 5000); + MESA_load_profile_uint_def(config_file, "OBJSCAN", "KAFKA_PRODUCE_OUTQ_SIZE", &g_objscan_info.produce_q_size, 100000); + MESA_load_profile_uint_def(config_file, "OBJSCAN", "KAFKA_REQUEST_ACKS", &g_objscan_info.kafka_req_ack, 0); + if(MESA_load_profile_uint_def(config_file, "OBJSCAN", "KAFKA_BROKSER_PORT", &kafka_port, 9092)<0) + { + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "Load config [OBJSCAN] KAFKA_BROKSER_PORT failed."); + return -1; + } + if(MESA_load_profile_string_nodef(config_file, "OBJSCAN", "KAFKA_BROKSER_IPLIST", tmp_buf, sizeof(tmp_buf))<0) + { + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "Load config [OBJSCAN] KAFKA_BROKSER_IPLIST failed."); + return -1; + } + + g_objscan_info.queue_msg = MESA_lqueue_create(1, g_objscan_info.queue_elem_size); + g_objscan_info.queue_delay = MESA_lqueue_create(1, g_objscan_info.queue_elem_size); + g_objscan_info.queue_analyze = MESA_lqueue_create(1, g_objscan_info.queue_elem_size); + + register_field_stat(); + return build_kafka_cluster_addrs(tmp_buf, kafka_port, g_objscan_info.kafka_brokers, 4096, g_objscan_info.log_runtime); +} + +int32_t main(int32_t argc, char **argv) +{ + pthread_t thread_desc; + pthread_attr_t attr; + u_int32_t i; + + wired_load_config(OBJSCAN_CONF_FILE); + if(read_config_and_init(OBJSCAN_CONF_FILE) || rdkafka_producer_init() || rdkafka_consumer_init() || avl_scan_engine_init()) + { + assert(0); + return -1; + } + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + object_store_global_init(); + g_objscan_info.instance = object_store_instance_new(OBJSCAN_CONF_FILE, "TANGO_CACHE", g_objscan_info.thread_num_fetch, g_objscan_info.log_runtime); + if(g_objscan_info.instance == NULL) + { + assert(0); + return -1; + } + + if(pthread_create(&thread_desc, &attr, thread_recv_kafka_msg, NULL)) + { + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "pthread_create(): %s", strerror(errno)); + return -1; + } + if(pthread_create(&thread_desc, &attr, thread_delay_msg_queue, NULL)) + { + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "pthread_create(): %s", strerror(errno)); + return -1; + } + if(pthread_create(&thread_desc, &attr, thread_fetch_object, NULL)) + { + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "pthread_create(): %s", strerror(errno)); + return -1; + } + + for(i=0; i<g_objscan_info.thread_num_anly; i++) + { + if(pthread_create(&thread_desc, &attr, thread_analyze_object, NULL)) + { + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_runtime, RLOG_LV_FATAL, "pthread_create(): %s", strerror(errno)); + return -1; + } + } + + /*statistics*/ + time_t now, remain; + long queue_msg, queue_delay, queue_anly, quque_kafka; + struct objscan_statistics last_statistic, inc_statistic; + long *pinc_statistic=(long*)&inc_statistic, *pnow_statistic=(long*)&g_objscan_info.statistic, *plast_statistic=(long*)&last_statistic; + + memset(&last_statistic, 0, sizeof(struct objscan_statistics)); + while(1) + { + now = time(NULL); + remain = g_objscan_info.fsstat_period- (now % g_objscan_info.fsstat_period); + sleep(remain); + + rd_kafka_poll(g_objscan_info.kafka_producer, 0); //��������Kafka��ͳ����Ϣ + for(i=0; i<sizeof(struct objscan_statistics)/sizeof(long); i++) + { + pinc_statistic[i] = pnow_statistic[i] - plast_statistic[i]; + } + last_statistic = g_objscan_info.statistic; + + for(i=0; i<MESSAGE_STATE_NUM; i++) + { + FS_operate(g_objscan_info.fsstat_handle, g_objscan_info.fsstat_field_ids[i], 0, FS_OP_SET, g_objscan_info.statistic.num[i]); + } + queue_msg = MESA_lqueue_get_count(g_objscan_info.queue_msg); + FS_operate(g_objscan_info.fsstat_handle, g_objscan_info.fsstat_status_ids[FSSTAT_ID_MSG_QUEUE], 0, FS_OP_SET, queue_msg); + queue_delay = MESA_lqueue_get_count(g_objscan_info.queue_delay); + FS_operate(g_objscan_info.fsstat_handle, g_objscan_info.fsstat_status_ids[FSSTAT_ID_DELAY_QUEUE], 0, FS_OP_SET, queue_delay); + queue_anly = MESA_lqueue_get_count(g_objscan_info.queue_analyze); + FS_operate(g_objscan_info.fsstat_handle, g_objscan_info.fsstat_status_ids[FSSTAT_ID_ANLYZ_QUEUE], 0, FS_OP_SET, queue_anly); + quque_kafka = rd_kafka_outq_len(g_objscan_info.kafka_producer); + FS_operate(g_objscan_info.fsstat_handle, g_objscan_info.fsstat_status_ids[FSSTAT_ID_kAFKA_P_Q], 0, FS_OP_SET, quque_kafka); + FS_passive_output(g_objscan_info.fsstat_handle); + + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_statistic, RLOG_LV_FATAL, "----------------------------------------------------------------------------------"); + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_statistic, RLOG_LV_FATAL, "SCAN_SUCC: %lu, HITTED: %lu, RCV_ERROR: %lu, DROP: %lu, EMPTY: %lu, ANLY_FAIL: %lu, OTH_FAIL: %lu", + pinc_statistic[MESSAGE_SUCC], pinc_statistic[MESSAGE_HITTED], pinc_statistic[MESSAGE_RCV_ERROR], pinc_statistic[MESSAGE_DROP], + pinc_statistic[MESSAGE_NOT_EXIST], pinc_statistic[MESSAGE_ANLY_FAIL], pinc_statistic[MESSAGE_OTH_FAIL]); + MESA_HANDLE_RUNTIME_LOGV2(g_objscan_info.log_statistic, RLOG_LV_FATAL, "MSG_QUEUE: %lu, DELAY_QUEUE: %lu, ANLY_QUEUE: %lu, KAFKA_P_Q: %lu", + queue_msg, queue_delay, queue_anly, quque_kafka); + } + return 0; +} + diff --git a/src/objectscanner_main.h b/src/objectscanner_main.h new file mode 100644 index 0000000..cbb326d --- /dev/null +++ b/src/objectscanner_main.h @@ -0,0 +1,97 @@ +#ifndef __OBJECT_SCANNER_MAIN_H__ +#define __OBJECT_SCANNER_MAIN_H__ + +#include <MESA/MESA_handle_logger.h> +#include <MESA/MESA_list_queue.h> +#include <MESA/field_stat2.h> + +#include "librdkafka/rdkafka.h" + +#include "objectscanner_kafka.h" + +#define OBJSCAN_CONF_FILE "./conf/objectscan.conf" + +#define MESA_HANDLE_RUNTIME_LOGV2(handle, lv, fmt, args...) \ + MESA_handle_runtime_log((handle), (lv), "OBJSCAN", "%s:%d, " fmt, __FILE__, __LINE__, ##args) + +enum FSSTAT_STATUS_ID +{ + FSSTAT_ID_MSG_QUEUE=0, + FSSTAT_ID_DELAY_QUEUE, + FSSTAT_ID_ANLYZ_QUEUE, + FSSTAT_ID_kAFKA_P_Q, + + FSSTAT_ID_NUM, +}; + +typedef struct __colom_global_info +{ + //system + MESA_lqueue_head queue_msg; + MESA_lqueue_head queue_delay; + MESA_lqueue_head queue_analyze; + u_int32_t queue_elem_size; + u_int32_t thread_num_anly; + u_int32_t thread_num_fetch; + u_int32_t delay_time_s; + u_int32_t anly_max_len; + + struct object_store_instance *instance; + + //scan engine + void *p_engine_handle; + void *p_i2n_handle; + + //Kafka// + u_int32_t kafka_req_ack; + u_int32_t produce_q_size; + u_int32_t consume_timeout_ms; + u_int32_t consume_from_latest; + char kafka_brokers[4096]; + char kafka_consu_name[128]; + rd_kafka_t *kafka_producer; + rd_kafka_t *kafka_consumer; + rd_kafka_topic_t *produc_topic; + + //LOGS + char root_log_dir[256]; + char appname[64]; + u_int32_t log_level; + int32_t sys_log_level; + void *log_runtime; + void *log_statistic; + + struct objscan_statistics statistic; + screen_stat_handle_t fsstat_handle; + char fsstat_dst_ip[64]; + char fsstat_appname[16]; + char fsstat_filepath[256]; + u_int32_t fsstat_period; + u_int32_t fsstatid_trig; + int32_t fsstat_dst_port; + int32_t fsstat_field_ids[MESSAGE_STATE_NUM]; + int32_t fsstat_status_ids[FSSTAT_ID_NUM]; +}objscan_global_info_t; + +#if(__GNUC__ * 100 + __GNUC_MINOR__ * 10 + __GNUC_PATCHLEVEL__ >= 410) +#define atomic_inc(x) __sync_add_and_fetch((x),1) +#define atomic_dec(x) __sync_sub_and_fetch((x),1) +#define atomic_add(x,y) __sync_add_and_fetch((x),(y)) +#define atomic_sub(x,y) __sync_sub_and_fetch((x),(y)) +typedef long atomic_t; +#define ATOMIC_INIT(i) { (i) } +#define atomic_read(x) __sync_add_and_fetch((x),0) +#define atomic_set(x,y) __sync_lock_test_and_set((x),y) +#else +typedef long atomic_t; +#define atomic_inc(x) ((*(x))++) +#define atomic_dec(x) ((*(x))--) +#define atomic_add(x,y) ((*(x))+=(y)) +#define atomic_sub(x,y) ((*(x))-=(y)) +#define ATOMIC_INIT(i) { (i) } +#define atomic_read(x) (*(x)) +#define atomic_set(x,y) ((*(x))=(y)) +#endif + +#endif + diff --git a/src/supoort/AVLSDK3.0_centos7_x64_20190520.rar b/src/supoort/AVLSDK3.0_centos7_x64_20190520.rar Binary files differnew file mode 100644 index 0000000..af85199 --- /dev/null +++ b/src/supoort/AVLSDK3.0_centos7_x64_20190520.rar diff --git a/src/supoort/antiy.7z b/src/supoort/antiy.7z Binary files differnew file mode 100644 index 0000000..20ac897 --- /dev/null +++ b/src/supoort/antiy.7z diff --git a/src/supoort/sr.txt b/src/supoort/sr.txt new file mode 100644 index 0000000..b5bece9 --- /dev/null +++ b/src/supoort/sr.txt @@ -0,0 +1 @@ +���߰�����
\ No newline at end of file |
