endurox-sys 0.1.1

Low-level FFI bindings for Enduro/X middleware
Documentation
# endurox-sys

Low-level Rust FFI bindings for [Enduro/X](https://www.endurox.org/) middleware.

Enduro/X is a high-performance, open-source middleware platform that implements the XATMI API. This crate provides safe and unsafe Rust bindings to the Enduro/X C API, enabling you to build distributed transaction processing applications in Rust.

## Features

- **XATMI API** - Complete bindings for `tpcall()`, `tpacall()`, `tpreturn()`, etc.
- **UBF Buffers** - Typed buffer manipulation with `Bchg()`, `Bget()`, etc.
- **Server Development** - Build Enduro/X servers with `atmisrvnomain()`
- **Client Development** - Create clients with `tpinit()`, `tpterm()`
- **Derive Macros** - Optional `#[derive(UbfStructDerive)]` for automatic serialization
- **Type Safety** - Safe wrappers around raw pointers and error handling

## Installation

Add this to your `Cargo.toml`:

```toml
[dependencies]
endurox-sys = { version = "0.1", features = ["ubf", "server"] }
```

### Prerequisites

- Enduro/X middleware installed and configured
- Required environment variables (see below)
- Oracle Instant Client (if using Oracle features)

### Environment Variables

#### `NDRX_HOME` (Required)
Points to the Enduro/X installation directory. Used by the build script to locate Enduro/X libraries and headers.

```bash
export NDRX_HOME=/opt/endurox
```

The build script uses this to:
- Link against Enduro/X libraries (`libatmi`, `libubf`, `libnstd`, etc.)
- Find header files during compilation

#### `NDRX_APPHOME` (Optional)
Points to your application's home directory. Used by the build script to locate UBF field table definitions (`ubftab/` directory) for generating Rust constants.

```bash
export NDRX_APPHOME=/path/to/your/app
```

When set, the build script looks for `*.fd.h` files in `$NDRX_APPHOME/ubftab/` and generates Rust constants for UBF field IDs. This allows you to use field constants like `T_NAME_FLD` directly in your code.

**Build-time behavior:**
- If `NDRX_APPHOME` is set: looks for `$NDRX_APPHOME/ubftab/*.fd.h`
- If not set: looks for `../ubftab/*.fd.h` (relative to crate directory, for local development)
- If no UBF tables found: generates empty constants file (build still succeeds)

**Example:**
```rust
use endurox_sys::*;

unsafe {
    // Use generated field constants
    Bchg(buffer, T_NAME_FLD, 0, name.as_ptr() as *mut i8, 0);
    Bchg(buffer, T_AMOUNT_FLD, 0, &amount as *const _ as *mut i8, 0);
}
```

## Usage

### Basic Client Example

```rust
use endurox_sys::*;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    unsafe {
        // Initialize connection
        tpinit(std::ptr::null_mut())?;
        
        // Allocate UBF buffer
        let buf = tpalloc(b"UBF\0".as_ptr() as *mut i8, std::ptr::null_mut(), 1024);
        
        // Call service
        let mut len = 1024;
        tpcall(
            b"MYSERVICE\0".as_ptr() as *mut i8,
            buf,
            0,
            &mut buf,
            &mut len,
            0
        )?;
        
        // Free buffer and disconnect
        tpfree(buf);
        tpterm();
    }
    
    Ok(())
}
```

### Server Example with Derive

```rust
use endurox_sys::*;

#[derive(UbfStructDerive)]
struct Request {
    #[ubf_field(1000)]
    transaction_id: String,
    
    #[ubf_field(1001)]
    amount: i64,
}

#[derive(UbfStructDerive)]
struct Response {
    #[ubf_field(2000)]
    status: String,
    
    #[ubf_field(2001)]
    message: String,
}

#[no_mangle]
pub extern "C" fn MYSERVICE(p_svc: *mut TPSVCINFO) {
    unsafe {
        let svc = &*p_svc;
        
        // Deserialize request
        let req = match Request::from_ubf(svc.data as *mut UBFH) {
            Ok(r) => r,
            Err(_) => {
                tpreturn(TPFAIL, 0, std::ptr::null_mut(), 0, 0);
                return;
            }
        };
        
        // Process request
        let resp = Response {
            status: "SUCCESS".to_string(),
            message: format!("Processed {}", req.transaction_id),
        };
        
        // Serialize response
        if resp.to_ubf(svc.data as *mut UBFH).is_ok() {
            tpreturn(TPSUCCESS, 0, svc.data, 0, 0);
        } else {
            tpreturn(TPFAIL, 0, std::ptr::null_mut(), 0, 0);
        }
    }
}
```

## Features

### `ubf`
Enables UBF buffer API bindings:
- `Bchg()`, `Bget()`, `Badd()`, `Bdel()`
- Field ID and type management
- Buffer allocation and manipulation

### `server`
Enables server-side bindings:
- `atmisrvnomain()` - Main server entry point
- `tpsvrinit()`, `tpsvrdone()` - Server lifecycle hooks
- `tpadvertise()`, `tpunadvertise()` - Service advertisement

### `client`
Enables client-side bindings:
- `tpinit()`, `tpterm()` - Connection management
- `tpcall()`, `tpacall()`, `tpgetrply()` - Service calls

### `derive`
Enables `#[derive(UbfStructDerive)]` macro for automatic UBF serialization.
Requires the [`endurox-derive`](https://crates.io/crates/endurox-derive) crate.

## Safety

Most functions in this crate are marked `unsafe` as they interact with C FFI and raw pointers. Safe wrappers can be found in higher-level crates built on top of `endurox-sys`.

Always ensure:
- Buffers are properly allocated before use
- `tpinit()` is called before any XATMI operations
- Resources are freed with `tpfree()` and `tpterm()`
- Error codes are checked after each operation

## Error Handling

Use `tperrno()` and `tpstrerror()` to get error information:

```rust
use endurox_sys::*;

unsafe {
    if tpcall(...).is_err() {
        let errno = tperrno();
        let error = std::ffi::CStr::from_ptr(tpstrerror(errno))
            .to_string_lossy();
        eprintln!("Error: {}", error);
    }
}
```

## Documentation

For complete API documentation, see [docs.rs/endurox-sys](https://docs.rs/endurox-sys).

For Enduro/X documentation, visit [www.endurox.org/dokuwiki](https://www.endurox.org/dokuwiki).

## License

Licensed under the MIT license. See [LICENSE](../LICENSE) for details.

## Related Crates

- [`endurox-derive`]https://crates.io/crates/endurox-derive - Derive macros for UBF serialization
- [`endurox`]https://crates.io/crates/endurox - High-level safe API (coming soon)