1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
use std::os::raw::{c_int,c_char};
use std::ffi::CStr;


pub const MOSQ_ERR_CONN_PENDING:i32 = -1;
pub const MOSQ_ERR_SUCCESS:i32 = 0;
pub const MOSQ_ERR_NOMEM:i32 = 1;
pub const MOSQ_ERR_PROTOCOL:i32 = 2;
pub const MOSQ_ERR_INVAL:i32 = 3;
pub const MOSQ_ERR_NO_CONN:i32 = 4;
pub const MOSQ_ERR_CONN_REFUSED:i32 = 5;
pub const MOSQ_ERR_NOT_FOUND:i32 = 6;
pub const MOSQ_ERR_CONN_LOST:i32 = 7;
pub const MOSQ_ERR_TLS:i32 = 8;
pub const MOSQ_ERR_PAYLOAD_SIZE:i32 = 9;
pub const MOSQ_ERR_NOT_SUPPORTED:i32 = 10;
pub const MOSQ_ERR_AUTH:i32 = 11;
pub const MOSQ_ERR_ACL_DENIED:i32 = 12;
pub const MOSQ_ERR_UNKNOWN:i32 = 13;
pub const MOSQ_ERR_ERRNO:i32 = 14;
pub const MOSQ_ERR_EAI:i32 = 15;
pub const MOSQ_ERR_PROXY:i32 = 16;

// extended error
pub const MOSQ_ERR_TIMEOUT:i32 = 16;

pub const MOSQ_LOG_NONE:i32 = 0x00;
pub const MOSQ_LOG_INFO:i32 = 0x01;
pub const MOSQ_LOG_NOTICE:i32 = 0x02;
pub const MOSQ_LOG_WARNING:i32 = 0x04;
pub const MOSQ_LOG_ERR:i32 = 0x08;
pub const MOSQ_LOG_DEBUG:i32 = 0x10;
pub const MOSQ_LOG_SUBSCRIBE:i32 = 0x20;
pub const MOSQ_LOG_UNSUBSCRIBE:i32 = 0x40;
pub const MOSQ_LOG_ALL:i32 = 0xFFFF;

pub const MOSQ_CONNECT_ERR_OK:i32 = 0;
pub const MOSQ_CONNECT_ERR_PROTOCOL:i32 = 1;
pub const MOSQ_CONNECT_ERR_BADID:i32 = 2;
pub const MOSQ_CONNECT_ERR_NOBROKER:i32 = 3;

// extended error
pub const MOSQ_CONNECT_ERR_TIMEOUT:i32 = 256;

pub type Mosq = c_int;
pub type Data = c_int;
pub type PwCallback = extern fn (buf: *mut c_char, size: c_int, rwflag: c_int, userdata: *mut Data)->c_int;

#[derive(Debug)]
#[repr(C)]
pub struct Message{
	pub mid: c_int,
	pub topic: *const c_char,
	pub payload: *const u8,
	pub payloadlen: c_int,
	pub qos: c_int,
	pub retain: u8
}

#[link(name = "mosquitto")]
extern {
    pub fn mosquitto_lib_version(major: *mut c_int, minor: *mut c_int, revision: *mut c_int) -> c_int;
    pub fn mosquitto_lib_init() -> c_int;
    pub fn mosquitto_lib_cleanup() -> c_int;
    pub fn mosquitto_new(id: *const c_char, clean_session: u8, obj: *const Data) -> *mut Mosq;
    pub fn mosquitto_destroy(mosq: *const Mosq);
    pub fn mosquitto_connect(mosq: *const Mosq, host: *const c_char, port: c_int, keepalive: c_int) -> c_int;
    pub fn mosquitto_reconnect(mosq: *const Mosq) -> c_int;
    pub fn mosquitto_disconnect(mosq: *const Mosq) -> c_int;
    pub fn mosquitto_strerror(err: c_int) -> *const c_char;
    pub fn mosquitto_user_data_set(mosq: *const Mosq, obj: *const Data);
    pub fn mosquitto_threaded_set(mosq: *const Mosq, threaded: u8) -> c_int;

    pub fn mosquitto_connect_callback_set(mosq: *const Mosq,
        callback: extern fn(*const Mosq, *mut Data, c_int)
    );
    pub fn mosquitto_publish_callback_set(mosq: *const Mosq,
        callback: extern fn(*const Mosq, *mut Data, c_int)
    );
    pub fn mosquitto_subscribe_callback_set(mosq: *const Mosq,
        callback: extern fn(*const Mosq, *mut Data, c_int)
    );

    pub fn mosquitto_message_callback_set(mosq: *const Mosq,
        callback: extern fn(*const Mosq, *mut Data, *const Message)
    );

    pub fn mosquitto_disconnect_callback_set(mosq: *const Mosq,
        callback: extern fn(*const Mosq, *mut Data, c_int)
    );
    pub fn mosquitto_unsubscribe_callback_set(mosq: *const Mosq,
        callback: extern fn(*const Mosq, *mut Data, c_int)
    );

    pub fn mosquitto_log_callback_set(mosq: *const Mosq,
        callback: extern fn(*const Mosq, *mut Data, c_int, *const c_char)
    );

    pub fn mosquitto_message_copy(copy: *mut Message, msg: *const Message) -> c_int;
    pub fn mosquitto_message_free(msg: *const *const Message);

    pub fn mosquitto_subscribe(mosq: *const Mosq, mid: *mut c_int, sub: *const c_char, qos: c_int) -> c_int;
    pub fn mosquitto_unsubscribe(mosq: *const Mosq,mid: *mut c_int, sub: *const c_char) -> c_int;

    pub fn mosquitto_publish(mosq: *const Mosq, mid: *mut c_int, topic: *const c_char,
        payloadlen: c_int, payload: *const u8, qos: c_int, retain: u8) -> c_int;

    pub fn mosquitto_will_set(mosq: *const Mosq, topic: *const c_char,
        payloadlen: c_int, payload: *const u8, qos: c_int, retain: u8) -> c_int;

    pub fn mosquitto_will_clear(mosq: *const Mosq) -> c_int;

    pub fn mosquitto_loop(mosq: *const Mosq, timeout: c_int, max_packets: c_int) -> c_int;
    pub fn mosquitto_loop_forever(mosq: *const Mosq, timeout: c_int, max_packets: c_int) -> c_int;

    pub fn mosquitto_topic_matches_sub(sub: *const c_char, topic: *const c_char, result: *mut u8);

    pub fn mosquitto_reconnect_delay_set(mosq: *const Mosq, reconnect_delay: c_int, reconnect_delay_max: c_int, reconnect_exponential_backoff: u8) -> c_int;

    pub fn mosquitto_tls_set(mosq: *const Mosq,
        cafile: *const c_char, capath: *const c_char, certfile: *const c_char, keyfile: *const c_char,
        pw_callback: Option<PwCallback>) -> c_int;

    pub fn mosquitto_tls_psk_set(mosq: *const Mosq,
        psk: *const c_char, identity: *const c_char, ciphers: *const c_char) -> c_int;
}

pub fn mosq_strerror(rc: c_int) -> String {
    unsafe {
        if rc == MOSQ_ERR_TIMEOUT {
            return "timeout".into();
        }
        let errs = mosquitto_strerror(rc);
        CStr::from_ptr(errs).to_str().unwrap().to_string()
    }
}

pub fn connect_error(rc: i32) -> &'static str {
    match rc {
    MOSQ_CONNECT_ERR_OK => "connect: ok",
    MOSQ_CONNECT_ERR_PROTOCOL => "connect: bad protocol version",
    MOSQ_CONNECT_ERR_BADID => "connect: id rejected",
    MOSQ_CONNECT_ERR_NOBROKER => "connect: broker unavailable",
    MOSQ_CONNECT_ERR_TIMEOUT => "connect: timed out",
    _ => "connect: unknown"
    }
}