simcore API version 0.9.1

1. General Overview

Include "simapi.h" and link to simcore/simcore.a to use functions described in this document. You also need to link to the following libraries from their subdirectories:

Do NOT link to stock versions of crypto++ or any other of these libraries that might already be installed on the system.

To identify contacts throughout the library, each one has a contact id, which is a 64-bit non-zero integer (simnumber). These ids are locally unique and persistent for each contact and user identity. API functions that work on a specific contact take this id as their first argument.

All IP addresses and simphone addresses are in ASCII.

Time is expressed as an unsigned integer containing the number of seconds since Jan 1st 1970 (GMT), unless noted otherwise.

threads

Functions described in this document are generally thread-safe and mostly non-blocking, unless stated otherwise.

Functions that work on specific data (this includes all simtype functions, referred to in type system, and all other utility functions) are thread-safe only as long as different threads work on different data. If you're writing the same data from more than one thread (or writing the data from one thread and reading it from another), you'd have to implement locking around the function calls.

The rest of the functions (except for sim_init_ and sim_exit_) are serialized, whereas the log_xxx_ functions are serialized separately from all other functions.

return values

Most API functions return an int; unless otherwise indicated, this is SIM_OK on success or an error code on failure. Error codes are defined in error.h (also check the description of the sim_error_xxx functions). Some functions return a simbool; this means true on success or false on failure.

For functions that return simtypes, see type system. Any simtypes that you get from API calls are not going to be modified by background threads. These values are yours until you free them explicitly; you do not need to make copies of them.

type system

simtypes are used throughout the library and in the API. A simtype is a pointer with a length and defines a value of one of four types:

SIMNUMBER

a 64-bit integer (simnumber if signed or simunsigned if unsigned).

SIMSTRING or SIMPOINTER

array of bytes; length does not count the terminating zero byte (if any).

SIMTABLE

an unordered list of SIMSTRING or SIMPOINTER keys with values of any of the four types.

SIMARRAY

an ordered list of values; all values must have the same type. The index of the first value of an array is one, not zero.

Type SIMNIL indicates that no value is present; SIMNIL is not allowed to be a member of either SIMTABLE or SIMARRAY, but may be returned by some functions to indicate an error. Each simtype used by the API already has a known type, so it is usually not necessary to check its type, but this might be done (if needed) by calling sim_get_type.

To free simtypes, the following functions are available:

SIMNUMBER

sim_number_free

SIMSTRING

sim_string_free

SIMTABLE

sim_table_free

SIMARRAY

sim_array_free

Freeing a table or an array also recursively frees all values stored within it. Freeing a SIMSTRING calls sim_free; freeing a SIMPOINTER does nothing (SIMPOINTER holds a pointer to user-managed memory). Freeing a SIMNIL with any of the four functions listed above is also explicitly allowed as a no-operation.

Storing a value other than SIMPOINTER into an array or a table (as a value OR as a key) causes the array/table to "consume" the value; it will be freed automatically when the array/table is freed. The caller CANNOT free it. Storing a SIMPOINTER value into an array or a table assumes that the value will "live" at least as long as the array or table does, and will be freed by the caller later.

A SIMSTRING can be converted to SIMPOINTER by calling sim_pointer_new_length, but if you store it to an array or a table, do make sure you do not free the original SIMSTRING before the array or table is freed.

The following functions are available to create simtypes:

SIMNIL

sim_nil

SIMNUMBER

sim_number_new

SIMSTRING

sim_string_new, sim_string_copy, sim_string_copy_length

SIMPOINTER

sim_pointer_new, sim_pointer_new_length

SIMTABLE

sim_table_new

SIMARRAY

sim_array_new_numbers, sim_array_new_strings, sim_array_new_tables, sim_array_new_arrays

To access a simtype value, use the following:

SIMNIL

if sim_get_type returns SIMNIL then simtype is sim_nil; sim_get_pointer returns NULL.

SIMNUMBER

sim_get_number returns the value of the number.

SIMSTRING or SIMPOINTER

sim_get_pointer returns pointer to the string, sim_get_length returns its length.

SIMTABLE

use functions sim_table_get_xxx, sim_table_set_xxx, sim_table_add_xxx, sim_table_delete_xxx. To enumerate all elements, use sim_table_walk_first and sim_table_walk_next_xxx. Note that sim_table_add will fail if key already exists while sim_table_set will overwrite. sim_table_count returns the number of elements in a table.

SIMARRAY

use functions sim_array_get_xxx and sim_array_set_xxx to access elements (i > 0); sim_get_length returns the number of elements. The sim_array_get_type function returns the type of all values of an array.

The following convention applies when passing simtypes as function arguments:

const simtype

function reads the contents of a simtype.

simtype

function reads and writes the contents of a simtype.

simtype *

function creates a new simtype and writes its contents.

For more details on simtypes please see the comments in simapi.h.

2. Initialize and Terminate the Library

int sim_init_(const char *user, unsigned version, const char *ui);

Must be called before calling any other functions. version must be 1, while ui should be the name and version number of your program.

user contains absolute pathname of a directory where files for this user identity are kept or an empty string to use the default location. If user is NULL, no files will be kept.

If sim_init_ returns anything other than SIM_OK, you can call it again later (after removing the error condition that caused the failure) to retry.

int sim_init_user_(const char *password);

Must be called after sim_init_ has returned successfully, in order to login.

password can be an empty string (for auto-login) or contain a secret key ("seed") or password that the saved secret key is encrypted with.

To login with a key that was just generated, but not saved, call sim_init_user_ with NULL password. In this case, sim_key_generate_ must have been previously called with zero size and must have finished successfully (SIM_EVENT_KEYGEN has been received).

If sim_init_user_ fails, it can be called again later to retry.

int sim_exit_user_(void);

Must be called in order to logout and notify contacts that you have gone offline.

If sim_exit_user_ returns SIM_OK, you can call sim_init_user_ if you want to login again. If sim_exit_user_ fails, the API is in an inconsistent state and you should exit your program without calling any API functions.

sim_exit_user_ might block for a long time, so it is a good idea to call it from a background thread if your program has something else to do at the same time.

int sim_exit_(void);

Optional function that can be called as the last thing in your program. It saves any open files and then frees all allocated resources from memory.

If sim_exit_ fails, the API is in an inconsistent state and you should exit your program without calling any API functions. If sim_exit_ returns SIM_OK, the only API function you should call afterwards is sim_init_ (if necessary).

3. Manage Keys

int sim_key_generate_(simtype *seed, const simtype entropy, int size, unsigned type);

If size is not zero, generate and return a new random seed of the specified size (number of bits) and type, and do not generate a key (caller has to call sim_string_free to release the returned *seed when done with it). entropy is either sim_nil or else a sequence of random bytes (SIMSTRING or SIMPOINTER), which is used as additional entropy for seed (key) generation.

If size is zero and type is not SIM_KEY_NONE, generate a random key of the specified type. If *seed is not sim_nil, also save key encrypted with *seed (which can be any zero-terminated string, which is NOT a valid seed) or if *seed is an empty string, save key without encrypting it.

If size is zero and type is SIM_KEY_NONE, generate a new key from *seed, which must be a valid seed (such as one returned by sim_key_generate_ when called with non-zero size). entropy must be sim_nil in this case.

Currently supported key types are:

If called with zero size (to generate a key), sim_key_generate_ will return successfully before it has finished its job. SIM_EVENT_KEYGEN will be received later to report progress, success or failure.

int sim_key_set_password_(const char *password, unsigned bits);

If *password is 0, save decrypted private key (enable auto-login in future). Otherwise, save private key encrypted with the specified password (which can be a seed or any other UTF-8 character string). If password is NULL, delete previously saved private key.

If bits is SIM_PASSWORD_BIT_DEFAULT, save key only if no key exists already. SIM_PASSWORD_BIT_OVERWRITE allows overwriting an existing saved key.

4. Connections

int sim_status_get_(unsigned *flags);

Return the current status (SIM_STATUS_xxx). If flags is not NULL, also sets *flags to a bit-wise combination (OR) of:

SIM_STATUS_FLAG_DHT_OUT

outgoing UDP peer-to-peer connectivity is available.

SIM_STATUS_FLAG_DHT_IN

incoming UDP peer-to-peer connectivity is available.

SIM_STATUS_FLAG_UDP_OUT

outgoing UDP connectivity is available.

SIM_STATUS_FLAG_UDP_IN

incoming UDP connectivity is available.

SIM_STATUS_FLAG_TCP_OUT

outgoing TCP connectivity is available.

SIM_STATUS_FLAG_TCP_IN

incoming TCP connectivity is available.

SIM_STATUS_FLAG_SSL_OUT

outgoing TCP connectivity to HTTPS port is available.

SIM_STATUS_FLAG_SSL_IN

incoming TCP connectivity to HTTPS port is available.

SIM_STATUS_FLAG_DNS

Name resolver has been answering DNS queries.

SIM_STATUS_FLAG_BOOT

DHT initialization servers have been contacted.

SIM_STATUS_FLAG_UPNP

incoming port forwarded over UPnP.

int sim_status_set_(int status);

Set the current status. status can be one of the following:

SIM_STATUS_ON

on-line and available.

SIM_STATUS_AWAY

on-line but appear "idle" (set manually).

SIM_STATUS_IDLE

on-line but appear "idle" (set automatically on inactivity).

SIM_STATUS_BUSY

on-line but not to be disturbed (sounds will not be played).

SIM_STATUS_HIDE

on-line but not watching (GUI not visible).

SIM_STATUS_OFF

off-line. Not connected to the DHT and not accepting or initiating connections.

SIM_STATUS_INVISIBLE

connected to the DHT but appear off-line. Outgoing connections can be made to any contact.

int sim_contact_connect_(simnumber id);
int sim_contact_disconnect_(simnumber id);

Call sim_contact_connect_ to try to connect immediately when opening a chat window, so that the first chat messages might be sent without delay when typed later. Call sim_contact_disconnect_ when the chat window is closed, so the library knows that this connection is no longer in active use and may close the network connection if/when necessary. Connections are reference-counted, so if you call sim_contact_connect_ for a given id, you MUST call sim_contact_disconnect_ for that id exactly the same number of times (even if sim_contact_connect_ returned an error).

int sim_contact_ping_(simnumber id, simnumber number, unsigned bits);

Send a special message that the contact will respond to (if alive) but the human user won't see. This function is intended mainly for testing and debugging.

number must be positive (or zero if you don't care). bits is a bit-wise combination (OR) of the following:

SIM_PING_BIT_CONNECT

first try to connect to contact if not currently connected.

SIM_PING_BIT_TCP

send a ping if connected to contact; SIM_EVENT_NET_PONG will be received when contact responds.

SIM_PING_BIT_NAT

initiate a NAT traversal attempt (only if currently connected through proxy); SIM_EVENT_NET_TRAVERSE will eventually be received.

5. Contacts

simtype sim_contact_get_(simnumber id, unsigned bits);

Return information about a contact. To get information about all contacts, call sim_contact_get_ with a zero id and CONTACT_BIT_DEFAULT. It will return an array containing all contact ids. Note that the indexes of this array are guaranteed to remain the same until sim_exit_user_ is called; if contacts are added to the list in the mean time, they will have new indexes.

bits is a bit-wise combination (OR) of the following:

CONTACT_BIT_DEFAULT

return all keys except the ones which have their own bits defined (below).

CONTACT_BIT_LATENCY

also return CONTACT_KEY_LATENCY. If CONTACT_BIT_DEFAULT is set together with CONTACT_BIT_LATENCY, also send a ping to measure latency.

CONTACT_BIT_VERIFY

also return CONTACT_KEY_VERIFY.

CONTACT_BIT_LINE

also return CONTACT_KEY_LINE.

CONTACT_BIT_STATS

also return CONTACT_KEY_CONNECT and CONTACT_KEY_HOSTS.

Returns sim_nil if contact doesn't exist (invalid id) or else a table with the following keys:

CONTACT_KEY_ADDRESS

string: simphone address of contact. Not to be used for anything except displaying (if requested explicitly by human user).

CONTACT_KEY_NICK

string: nickname in UTF-8 encoding.

CONTACT_KEY_OWN_NICK

string: contact's own nickname in UTF-8 encoding. May be missing if not known.

CONTACT_KEY_SEEN

number: time when contact was last seen. May be zero if not known.

CONTACT_KEY_STATUS

number: current status (SIM_STATUS_ON, SIM_STATUS_AWAY, SIM_STATUS_BUSY, SIM_STATUS_HIDE or SIM_STATUS_OFF); SIM_STATUS_INVISIBLE means implicit logout (disappeared without logging out).

CONTACT_KEY_FLAGS

number: communication rights. A bit-wise combination (OR) of the following:

  • CONTACT_FLAG_VERIFIED: contact is "verified manually"
  • CONTACT_FLAG_VERIFY: i am verified by contact
  • CONTACT_FLAG_UTF: contact allows UTF-8 chat messages
  • CONTACT_FLAG_XFER: contact allows file transfers
  • CONTACT_FLAG_AUDIO: contact allows audio calls
  • CONTACT_FLAG_TYPE: contact is now typing
  • CONTACT_FLAG_TYPING_Y: send typing notification to contact
  • CONTACT_FLAG_TYPING_N: do not send typing notification to contact
  • CONTACT_FLAG_UTF_Y: allow chat messages from contact
  • CONTACT_FLAG_UTF_N: disallow chat messages from contact
  • CONTACT_FLAG_EDIT_Y: allow contact to edit sent messages
  • CONTACT_FLAG_EDIT_N: disallow contact to edit sent messages
  • CONTACT_FLAG_XFER_Y: allow file transfers from contact
  • CONTACT_FLAG_XFER_N: disallow file transfers from contact
  • CONTACT_FLAG_AUDIO_Y: allow audio calls from contact
  • CONTACT_FLAG_AUDIO_N: disallow audio calls from contact
  • CONTACT_FLAG_ECHO_Y: request echo cancellation from contact
  • CONTACT_FLAG_ECHO_N: request no echo cancellation from contact
  • CONTACT_FLAG_HISTORY_Y: log chat history with contact
  • CONTACT_FLAG_HISTORY_N: do not log chat history with contact.

CONTACT_KEY_AUTH

number: authorization level, which is one of the following:

  • CONTACT_AUTH_ACCEPTED: contact is authorized for communication
  • CONTACT_AUTH_NEW: contact request has not been accepted yet
  • CONTACT_AUTH_DELETED or CONTACT_AUTH_REVOKED: contact is blocked permanently
  • CONTACT_AUTH_BLOCKED: contact is suppressed (blocked temporarily)
  • CONTACT_AUTH_FORGET: contact has been forgotten.

CONTACT_KEY_EDIT

number: number of last sent chat messages that contact allows you to edit. Zero if no editing is desired.

CONTACT_KEY_IP

string: current IP address. Missing if unknown or not connected.

CONTACT_KEY_LOCATION

string: IP address where contact was last located. Missing if never connected.

CONTACT_KEY_CONNECT

string: proxy IP address or/and connection type. Missing if not currently connected.

CONTACT_KEY_LATENCY

number: packet round-trip time in milliseconds. Zero means unknown; missing if not currently connected.

CONTACT_KEY_HOSTS

array of strings: list of contact's DynDNS hostnames. Missing or empty if none.

CONTACT_KEY_CIPHER

string: name of cipher last used by contact. Empty if never connected.

CONTACT_KEY_KEY_SIZE

number: contact's key size (number of bits). May be zero if not known; missing for CONTACT_VIP_TEST.

CONTACT_KEY_VERIFY

string: own verification token for this contact in ASCII. Missing if not currently available.

CONTACT_KEY_LINE

string: contact's info line in UTF-8 encoding. Empty string if no info line.

CONTACT_KEY_AUDIO

string: contact's call state. The following values are currently defined:

  • missing (no value): not talking and not connected
  • CONTACT_AUDIO_HANGUP: not talking
  • CONTACT_AUDIO_OUTGOING: made an outgoing call and waiting for an answer
  • CONTACT_AUDIO_INCOMING: an incoming call arrived and waiting for pickup
  • CONTACT_AUDIO_TALKING, CONTACT_AUDIO_UDP: talking now.

CONTACT_KEY_VIP

string: type of contact, which is one of the following:

  • missing (no value): normal contact (not a special contact)
  • CONTACT_VIP_MYSELF: yourself
  • CONTACT_VIP_TEST: special contact for audio test
  • CONTACT_VIP_SYSTEM: the simphone system contact.

For contacts that return CONTACT_AUTH_FORGET, CONTACT_AUTH_REVOKED or CONTACT_AUTH_DELETED, the following keys may be missing (in addition to the already mentioned possibly missing keys): CONTACT_KEY_STATUS, CONTACT_KEY_KEY_SIZE, CONTACT_KEY_LINE.

The returned data (when called with either zero or non-zero id) is guaranteed to remain accessible until sim_contact_free_ is called (but note that network events might update it, in which case you should call sim_contact_get_ again to retrieve the new data).

Caller has to call sim_contact_free_ to release the returned value when done with it.

void sim_contact_free_(simtype contact);

Must be called with a value returned by sim_contact_get_ as an argument. It will release the copy of the contact information from memory.

int sim_contact_add_(const char *address, simnumber *id);

Add a new contact with the specified simphone address and save the contacts file. Checks the validity of the simphone address and corrects it if necessary (and possible) and (if id is not NULL) also sets *id to the new contact id.

If the contact to be added already exists, this function will authorize the contact without returning an error.

int sim_contact_set_(simnumber id, const char *key, const simtype value);

Set information about a contact to the given value and save the contacts file. If id is zero, set your own information. key is one of:

CONTACT_KEY_NICK

set a new nickname for contact (string) in UTF-8 encoding (empty string to reset to contact's own nickname).

CONTACT_KEY_LINE

set a new info line for contact (string) in UTF-8 encoding (empty string to remove info line). Only with zero id.

CONTACT_KEY_FLAGS

modify communication rights. value (number) is a bit-wise combination (OR) of the following:

  • CONTACT_FLAG_TYPE_Y: notify contact that i am now typing
  • CONTACT_FLAG_TYPE_N: notify contact that i am not typing any more
  • CONTACT_FLAG_TYPING_Y: send typing notification to contact
  • CONTACT_FLAG_TYPING_N: do not send typing notification to contact
  • CONTACT_FLAG_UTF_Y: allow chat messages from contact
  • CONTACT_FLAG_UTF_N: disallow chat messages from contact
  • CONTACT_FLAG_EDIT_Y: allow contact to edit sent messages
  • CONTACT_FLAG_EDIT_N: disallow contact to edit sent messages
  • CONTACT_FLAG_XFER_Y: allow file transfers from contact
  • CONTACT_FLAG_XFER_N: disallow file transfers from contact
  • CONTACT_FLAG_AUDIO_Y: allow audio calls from contact
  • CONTACT_FLAG_AUDIO_N: disallow audio calls from contact
  • CONTACT_FLAG_ECHO_Y: request echo cancellation from contact
  • CONTACT_FLAG_ECHO_N: request no echo cancellation from contact
  • CONTACT_FLAG_HISTORY_Y: log chat history with contact
  • CONTACT_FLAG_HISTORY_N: do not log chat history with contact.

Only bits that are set in the value mask are modified. To clear both "yes" and "no" flags, you need to SET both in the flags mask.

CONTACT_KEY_VERIFY

set contact verification flag. value (string) contains verification token or is empty (to unverify contact).

CONTACT_KEY_AUTH

set authorization level of contact (not with zero id). value (number) is one of the following:

  • CONTACT_AUTH_ACCEPTED: accept (authorize) a contact
  • CONTACT_AUTH_BLOCKED: suppress (temporarily block) contact
  • CONTACT_AUTH_DELETED: delete (permanently block) contact
  • CONTACT_AUTH_FORGET: remove (forget) contact.

Note that forgotten contacts are unblocked (would be able to send a contact request) on next login.

6. Chat Messages

int sim_msg_send_utf_(simnumber id, simtype text, simunsigned *idx);

Send a chat message, which must be a text string encoded in UTF-8. An index that identifies the message (can be given to sim_msg_edit_utf_ and sim_msg_get_) is returned as *idx.

If message text contains multiple lines, they can be separated by line feed (0x0A) characters, but it is recommended to send each line as a separate message instead.

Do NOT free the text string after the function has returned; if it is a SIMSTRING, it will be freed either before sim_msg_send_utf_ has returned, or when sim_msg_remove_, sim_msg_load_ or sim_exit_user_ is called. If it is a SIMPOINTER, it is your responsibility to free it after you have called one of these three functions.

int sim_msg_edit_utf_(simnumber id, simtype text, simunsigned idx);

Change a previously sent chat message identified by the given index. Freeing of the message text string has to happen by the same rules as with sim_msg_send_utf_.

int sim_msg_remove_(simnumber id, simunsigned idx);

Permanently delete a chat message from local chat history. The message string is removed immediately from both memory and history file, an action that cannot be undone. If the message was sent but not yet received, it will not be received; if it was sent and received, it cannot be changed after this function has been called.

simtype sim_msg_get_(simnumber id, simunsigned idx);

Read message from/to contact with the given index. Indexes start at 1 and are guaranteed to remain the same until either sim_msg_load_ or sim_exit_user_ is called.

The returned value is sim_nil if an (invalid argument) error occurred or else it is a table with the following keys:

SIM_CMD_MSG_STATUS

number: message status

  • SIM_MSG_INCOMING: message was received from contact
  • SIM_MSG_PENDING, SIM_MSG_SENT: message was sent to contact but is not yet acknowledged
  • SIM_MSG_ACKNOWLEDGED, SIM_MSG_DELIVERED: message was sent to contact and contact has received it
  • SIM_MSG_NOTSENT: message cannot yet be sent to contact (not connected)
  • SIM_MSG_UNSENT, SIM_MSG_UNDELIVERED, SIM_MSG_NOTDELIVERED: message was reported in SIM_EVENT_NOTSENT.

SIM_CMD_MSG_TYPE

number: SIM_MSG_TYPE_UTF or SIM_MSG_TYPE_SYSTEM.

SIM_CMD_MSG_TIME

number: time when message was sent.

SIM_CMD_MSG_RECEIVED

number: time when message was received. Missing (zero) if not received.

SIM_CMD_MSG_EDIT

number: time when message was last edited. Missing (zero) if not edited.

SIM_CMD_MSG_HANDLE

number: file transfer handle. Missing (zero) if unknown.

SIM_CMD_MSG_TEXT

string: message text in UTF-8 encoding. Missing if message was removed.

SIM_CMD_MSG_SENDER

string: nickname of user who sent the message (contact or yourself).

SIM_CMD_MSG_NICK

string: nickname of contact when message was sent or received.

Caller has to call sim_msg_free_ to release the returned table when done with it.

void sim_msg_free_(simtype msg);

Must be called with a value returned by sim_msg_get_ as an argument. It will free the returned table but not release the message text or nickname from memory; that happens automatically when sim_msg_remove, sim_msg_load_ or sim_exit_user_ is called.

simunsigned sim_msg_count_(simnumber id);

Return the highest message index that can currently be given as an argument to sim_msg_get_. More messages may arrive at any time.

int sim_msg_load_(simnumber id, simunsigned number);

Load the last number of messages from history file (and unload all others, except pending messages). To clear the message buffer, call with zero number. To load the whole chat history into the buffer, call with a very large number.

This function invalidates all message indexes and frees the text and nicknames of all messages.

sim_msg_load_ might block for a long time if there are many chat messages.

7. File Transfer

int sim_xfer_send_file_(simnumber id, const simtype pathname, simnumber *handle);

Send a file to contact; its pathname is a zero-terminated text string encoded in UTF-8. A positive number that uniquely identifies the file (can be given to sim_xfer_set_ and sim_xfer_get_) is returned as *handle.

simtype sim_xfer_get_(simnumber id, simnumber handle, unsigned bits);

If bits is SIM_XFER_BIT_DEFAULT, return sim_nil if an (invalid argument) error occurred or else return information about a file transfer with the given handle as a table with the following keys:

SIM_CMD_XFER_SEND_TYPE

string: state of file transfer, which is one of the following:

  • SIM_XFER_TYPE_DONE, SIM_XFER_TYPE_INIT, SIM_XFER_TYPE_WAIT, SIM_XFER_TYPE_HOLD, SIM_XFER_TYPE_SEND: outgoing transfer
  • SIM_XFER_TYPE_WIPE, SIM_XFER_TYPE_HASH, SIM_XFER_TYPE_RECV, SIM_XFER_TYPE_DATA, SIM_XFER_TYPE_EXEC: incoming transfer.

SIM_CMD_XFER_SEND_NAME

string: name of file (pathname for outgoing transfers).

SIM_CMD_XFER_SEND_SIZE

number: size of file in bytes.

SIM_CMD_XFER_SEND_TIME

number: time when file was sent (nanoseconds).

SIM_CMD_XFER_OFFSET

number: number of bytes that have been received already.

SIM_CMD_XFER_CLOSE_ERROR

number: SIM_OK or error code which caused file transfer failure.

If handle is SIM_XFER_GET_RECEIVED or SIM_XFER_GET_SENT, return information about all incoming or outgoing file transfers with a contact. That information is returned as a table with the same keys, but its values are arrays. Additionally, SIM_CMD_XFER_SEND_HANDLE is present as a key; its value is an array of numbers that contains the handles of all returned file transfers. A single file transfer is thus defined by the values of all keys indexed by the same index in the returned arrays.

If handle is SIM_XFER_GET_INFO, return general information about file transfers with a contact, as a table which includes some of the following keys:

SIM_XFER_GET_INFO_PAUSE

number: usually zero or else the same handle given as SIM_XFER_TYPE_PAUSE (or a negated handle value) to indicate the current pause or resume state with the given contact.

SIM_XFER_GET_INFO_CURRENT

number: handle of currently running file transfer. Missing if no current file transfer.

SIM_XFER_GET_INFO_DURATION

number: number of milliseconds for which the transfer has been currently running. Missing if no current file transfer or if the running time is not yet known.

SIM_XFER_GET_INFO_TRANSFERRED

number: number of bytes transferred during the current session. Present only if the value of SIM_XFER_GET_INFO_DURATION is also positive.

SIM_XFER_GET_INFO_RECEIVED

string: pathname of the received (download) subdirectory; missing if none. Present only if bits is SIM_XFER_BIT_EXTENDED.

SIM_XFER_GET_INFO_SENT

string: pathname of the sent (upload) subdirectory; missing if none. Present only if bits is SIM_XFER_BIT_EXTENDED.

Unlike all other functions, sim_xfer_get_ does include the terminating zero in lengths of returned file names (SIM_CMD_XFER_SEND_NAME) and pathnames (SIM_XFER_GET_INFO_RECEIVED and SIM_XFER_GET_INFO_SENT).

void sim_xfer_free_(simtype xfer);

Must be called with a value returned by sim_xfer_get_ as an argument. It will free the returned table from memory.

int sim_xfer_set_(simnumber id, simnumber handle, const char *type);

Control an already existing file transfer. type is one of:

SIM_XFER_TYPE_PAUSE

temporarily stop file transfers with contact if handle is SIM_CMD_XFER_INIT_PAUSE_ALL or resume them if handle is SIM_CMD_XFER_INIT_PAUSE_NONE. A valid handle (previously returned by sim_xfer_send_file_ or sim_xfer_get_) resumes a specific file transfer.

SIM_XFER_TYPE_CANCEL

trigger an immediate and permanent failure of file transfer. handle may be zero to fail all file transfers with contact or non-zero to fail a specific file transfer.

SIM_XFER_TYPE_FREE

optionally release data cached in memory but not returned by sim_xfer_get_. This function can be used when future calls to sim_xfer_get_ do not seem likely.

8. Audio Calls

These functions can be called before sim_init_user_ or after sim_exit_user_ but in this case id must be either CONTACT_ID_KEYGEN or CONTACT_ID_TEST; any other id can be used only if called after sim_init_user_ and before sim_exit_user_.

int sim_audio_call_(simnumber id);

Call a contact or accept an incoming call. Use CONTACT_ID_TEST to make a test call or CONTACT_ID_KEYGEN to make a test call to collect entropy for secret key generation. When using CONTACT_ID_KEYGEN to generate a seed, you need to set the crypto.entropy configuration parameter to the seed size in bits before making the call. When using CONTACT_ID_KEYGEN to generate a key, you need to reset the same parameter to its default value before making the call.

int sim_audio_hangup_(simnumber id);

Hangup or decline call from contact, or end an outgoing call.

simnumber sim_audio_check_talking_(void);

Return id of contact which is currently talking, or zero if nobody's talking.

int sim_sound_start_(const char *sound, int count);

Play sound with the specified name. If count is zero, play repeatedly until stop. Otherwise, play the specified number of times and stop.

int sim_sound_stop_(const char *sound);

Stop playing the specified sound immediately.

9. Configuration Parameters

int sim_param_get_limits_(const char *param, simtype *def, int *min, int *max, const char **description);

Return the default value and, if applicable, minimal and maximal values of the specified configuration parameter. Any of the pointers might be NULL if not interested in that value. If parameter value is a list of strings, sim_array_free must be called to release the returned *def.

The returned *description is a human-readable string that describes the parameter; it may be NULL if no description is available.

simtype sim_param_get_(const char *param);

Return value of configuration parameter with the specified name. If name is NULL, return all configuration parameters as a table keyed by parameter name.

void sim_param_free_(simtype value);

Must be called with a value returned by sim_param_get_ as an argument. It will release the copy of the parameter value from memory.

int sim_param_set_(const char *param, const simtype value, int permanent);

Set value of the specified configuration parameter. permanent is one of:

To unset a parameter, call with sim_nil value and SIM_PARAM_USER.

If param is NULL, set values of multiple configuration parameters (value is a table keyed by parameter name).

10. System Information

simtype sim_list_info_(unsigned bits);

Return system information. bits is a bit-wise combination (OR) of the following:

SIM_INFO_BIT_NET

return network status (SIM_INFO_NET_xxx).

SIM_INFO_BIT_AUDIO

return lists of currently available audio device names (SIM_INFO_AUDIO_xxx).

SIM_INFO_BIT_CRYPT

return list of supported ciphers (SIM_INFO_CRYPT_CIPHERS).

Returns a table with the following keys:

SIM_INFO_NET_IP

string: own IP address (may be an intranet address if UPnP is not in use).

SIM_INFO_NET_DHT_GOOD

number: number of good DHT nodes.

SIM_INFO_NET_DHT_DUBIOUS

number: number of dubious DHT nodes.

SIM_INFO_NET_DHT_BLOCKED

number: number of temporarily blacklisted DHT nodes.

SIM_INFO_NET_DHT_BAD

number: number of permanently blacklisted DHT nodes.

SIM_INFO_AUDIO_INPUT

array of strings: list of recording devices. Each element is a device name.

SIM_INFO_AUDIO_OUTPUT

array of strings: list of playback devices. Each element is a device name.

SIM_INFO_CRYPT_CIPHERS

table: supported ciphers. Each key is a cipher name, while value is a number, which is zero if that cipher is not preferred.

Caller has to call sim_list_free to release the returned table when done with it.

simtype sim_list_versions(void);

Return list of library versions as a table. Each key is a name string, while value is a version string.

Caller has to call sim_list_free to release the returned table when done with it.

void sim_list_free(simtype list);

Must be called with a value returned by sim_list_versions or sim_list_info_ as an argument. It will release the returned table from memory.

11. Events

Notification about anything that happens can be received asynchronously by registering event handlers, if interested. This means that user event handlers will be called from different threads; synchronization between these handlers and the main thread must be implemented, if necessary. You should avoid using a lot of stack space in event handlers or else you may trigger a stack overflow.

Each event can be registered multiple (or zero) times. To do that, use:

int sim_event_register_(const char *name, simevent *handler, simevent **oldhandler);

Register an event handler; the old handler for this event is stored in *oldhandler. The returned *oldhandler may be NULL if no other handler has been registered; otherwise, the new event handler MUST call the old one before it exits, and use exactly *oldhandler to do so. Do not copy or move the returned pointer.

The normal use of sim_event_register_ is to call it immediately after sim_init_.

typedef void (simevent) (simnumber id, const simtype event);

The first argument of a simevent handler callback is the contact id associated with that event (can be zero for events that are not associated with any contact). The second argument is a table containing data relevant to each event type; values within this table are generally accessible only from within the event handler.

The following event types are currently defined:

SIM_EVENT_FATAL. Fatal error has occurred. Two table keys:

SIM_EVENT_FATAL

number: error code which is SIM_OK if the error is not recoverable.

SIM_CMD_MSG_TEXT

string: fatal error string in UTF-8 encoding.

SIM_EVENT_FATAL can be handled by blocking until the fatal error condition has (hopefully) gone away. An error message (without trying to allocate memory) could be displayed to the user and after user input, you can return in order to retry or ignore the failed action. If SIM_EVENT_FATAL is not handled, the library will just _exit() you.

Note that the error string might be missing in certain circumstances, so this case needs to be handled too.

SIM_EVENT_CONTACT. List of contacts has changed. One table key:

SIM_EVENT_CONTACT

number: error code or SIM_OK if no error.

SIM_OK usually means that a contact with the given id has been added to the contact list either as an accepted contact, or (by default) as CONTACT_VIP_NEW. In certain cases, the contact might be missing from the contact list (because it could not be added).

SIM_EVENT_STATUS. Contact status or information has changed. One to seven table keys:

SIM_EVENT_STATUS

number: old (previous) contact status. Missing with artificial flags events.

CONTACT_KEY_STATUS

number: new (current) status (SIM_STATUS_ON, SIM_STATUS_AWAY, SIM_STATUS_BUSY, SIM_STATUS_HIDE or SIM_STATUS_OFF); SIM_STATUS_INVISIBLE means implicit logout (disappeared without logging out).

CONTACT_KEY_FLAGS

number: current communication rights. A bit-wise combination (OR) of CONTACT_FLAG_VERIFY, CONTACT_FLAG_UTF, CONTACT_FLAG_XFER, CONTACT_FLAG_AUDIO and CONTACT_FLAG_TYPE.

CONTACT_KEY_EDIT

number: number of last sent chat messages that can be edited.

CONTACT_KEY_OWN_NICK

string: old (previous) nickname in UTF-8 encoding.

CONTACT_KEY_NICK

string: new (current) nickname in UTF-8 encoding.

CONTACT_KEY_LINE

string: contact's current info line in UTF-8 encoding; empty string means contact's info line has been removed.

CONTACT_KEY_STATUS is present in the table only if status has changed. CONTACT_KEY_FLAGS is present only if communication rights have changed. CONTACT_KEY_EDIT is present only if the allowed number of last messages to edit has changed. CONTACT_KEY_NICK and CONTACT_KEY_OWN_NICK are present only if nickname has changed. CONTACT_KEY_LINE is present only if info line has changed.

SIM_EVENT_STATUS is received with zero id when your status has been automatically changed to SIM_STATUS_OFF in order to prevent data loss.

SIM_EVENT_MSG. Incoming chat message. Two table keys:

SIM_EVENT_MSG

number: index of received message (can be given to sim_msg_get_).

SIM_CMD_MSG_TEXT

string: message text in UTF-8 encoding.

SIM_EVENT_EDIT. Edit of a previously received chat message. Two table keys:

SIM_EVENT_EDIT

number: index of message being edited (can be given to sim_msg_get_).

SIM_CMD_MSG_TEXT

string: new message text in UTF-8 encoding.

SIM_EVENT_SENT. Outgoing chat messages have been sent. One table key:

SIM_EVENT_MSG

array of numbers: list of sent messages (may be empty). Each element is a message index.

SIM_EVENT_NOTSENT. Outgoing chat messages have not been sent yet. One table key:

SIM_EVENT_MSG

array of numbers: list of not sent messages. Each element is a message index.

SIM_EVENT_XFER. File transfer state change or file name change. Three table keys:

SIM_EVENT_XFER

string: old file transfer state type (as previously returned by sim_xfer_get_) or old file name.

SIM_CMD_XFER_SEND_TYPE

string: new file transfer state type (as would be returned by sim_xfer_get_) or new file name.

SIM_CMD_XFER_SEND_HANDLE

number: file transfer handle (as returned by sim_xfer_get_).

If the value of SIM_CMD_XFER_SEND_HANDLE is SIM_XFER_GET_RECEIVED or SIM_XFER_GET_SENT, this is a file name change. SIM_EVENT_XFER and SIM_CMD_XFER_SEND_TYPE contain old and new name of file in the received or sent subdirectory. If both of them are non-empty, a file has been renamed. If only SIM_CMD_XFER_SEND_TYPE is empty, a file has been deleted. If only SIM_EVENT_XFER is empty, a file has been created.

Otherwise, this event indicates a file transfer state change. If both SIM_EVENT_XFER and SIM_CMD_XFER_SEND_TYPE are non-empty, only a type change has taken place. If only SIM_EVENT_XFER is empty, the type has not changed, but something else returned by sim_xfer_get_ has. If only SIM_CMD_XFER_SEND_TYPE is empty, the position of this file transfer has changed, but nothing else has.

If both SIM_EVENT_XFER and SIM_CMD_XFER_SEND_TYPE are empty, this event indicates creation or destruction of an incoming file transfer (the value of SIM_CMD_XFER_SEND_HANDLE is negated on destruction).

SIM_EVENT_AUDIO. Call state change. Two table keys:

SIM_EVENT_AUDIO

string: old (previous) call state (as CONTACT_KEY_AUDIO returned by sim_contact_get_).

CONTACT_KEY_AUDIO

string: current call state (as CONTACT_KEY_AUDIO returned by sim_contact_get_).

  • CONTACT_AUDIO_CALLING means that outgoing call is initiated but not even connected yet
  • CONTACT_AUDIO_RINGING means that outgoing call is now ringing and still waiting for an answer
  • CONTACT_AUDIO_UDP means that a call already in progress is now running over UDP.

SIM_EVENT_SPEECH. Indicate current speech level. Three table keys:

SIM_EVENT_SPEECH

number: error code or SIM_OK if no error.

SIM_EVENT_SPEECH_PROBABILITY

number: speech probability.

SIM_EVENT_SPEECH_PROGRESS

number: progress of entropy collection (per cent).

Received with CONTACT_ID_KEYGEN or CONTACT_ID_TEST id during audio test, or with a contact id otherwise. The probability level is between SIM_EVENT_SPEECH_MIN and SIM_EVENT_SPEECH_MAX, or it is SIM_EVENT_SPEECH_END to indicate end of speech recording (only when id is CONTACT_ID_KEYGEN or CONTACT_ID_TEST).

SIM_EVENT_SPEECH_PROGRESS makes sense only when id is CONTACT_ID_KEYGEN.

SIM_EVENT_KEYGEN. Public key generation is taking place. One or two table keys:

SIM_EVENT_KEYGEN

number: error code (if failed).

SIM_EVENT_KEYGEN_TIME

number: estimated key generation time in seconds.

SIM_EVENT_KEYGEN_ADDRESS

string: new simphone address if generated; id is non-zero only in this case.

Received multiple times while generating an RSA key. After the initial time estimation, other non-zero (positive or negative) values of SIM_EVENT_KEYGEN_TIME are received as updates of the initial time estimation. When key generation has finished, this event is finally received without a value for SIM_EVENT_KEYGEN_TIME.

SIM_EVENT_HISTORY. System message has just been generated. Five table keys:

SIM_EVENT_HISTORY

number: index of system message or zero if none.

SIM_CMD_MSG_STATUS

number: message status (as described for sim_msg_get_).

SIM_CMD_MSG_TIME

number: time when message was sent or zero if generated locally. Missing if unknown.

SIM_CMD_MSG_RECEIVED

number: time when event started to happen.

SIM_CMD_MSG_HANDLE

number: file transfer handle or zero.

SIM_CMD_MSG_TEXT

string: as defined by the following two tables.

The following system messages are currently defined with SIM_MSG_INCOMING status:

STATUS OFF

multiple login forced my own logout.

STATUS ON

multiple login tried to force the other side to logout.

FILE SEND size name

contact initiated a file transfer.

FILE RECV 0 name

file transfer to contact finished successfully.

FILE RECV err name

contact failed to receive file.

FILE CANCEL 0 name

contact cancelled a file transfer from contact.

FILE CANCEL err name

contact failed to send file.

FILE REJECT 0 name

contact cancelled a file transfer to contact.

FILE REJECT err name

contact failed to receive file.

CALL START

incoming call was answered.

CALL FAILED err

contact tried to make an incoming call but couldn't connect.

CALL FAILED

contact tried to make an incoming call but gave up before he could connect.

CALL HANGUP err

there was an outgoing call to contact in progress but the other side failed to initiate or start it.

CALL HANGUP

the other side initiated a hangup while there was an outgoing call to contact in progress.

CALL HUNGUP err

there was an incoming call from contact in progress but the other side failed to initiate or start it.

CALL HUNGUP

the other side initiated a hangup while there was an incoming call from contact in progress.

CALL ABORT err

there had been an incoming call from contact but socket was disconnected.

CALL ABORT

contact gave up on an incoming call before it could be answered.

CALL BUSY err

had made an outgoing call to contact but the other side failed to receive or answer it.

CALL BUSY

had made an outgoing call to contact but the other side declined the call.

The following system messages are currently defined with status other than SIM_MSG_INCOMING:

STATUS OFF

multiple login forced my own logout.

STATUS ON

multiple login did not force my own logout.

FILE SEND size name

initiated a file transfer to contact.

FILE RECV 0 name

file transfer from contact finished successfully.

FILE RECV err name

failed to receive file from contact.

FILE CANCEL 0 name

cancelled a file transfer to contact.

FILE CANCEL err name

failed to send file to contact.

FILE REJECT 0 name

cancelled a file transfer from contact.

FILE REJECT err name

failed to receive file from contact.

CALL START

outgoing call was answered.

CALL FAILED err

made an outgoing call but couldn't connect to contact.

CALL FAILED

had made an outgoing call but couldn't connect to contact before hangup was initiated locally.

CALL HANGUP err

socket was disconnected while there was an outgoing call to contact in progress.

CALL HANGUP

hangup was initiated locally while there was an outgoing call to contact in progress.

CALL HUNGUP err

socket was disconnected while there was an incoming call from contact in progress.

CALL HUNGUP

hangup was initiated locally while there was an incoming call from contact in progress.

CALL ABORT err

had made an outgoing call to contact but socket was disconnected.

CALL ABORT

had made an outgoing call to contact before hangup was initiated locally.

CALL BUSY err

failed to receive or answer incoming call.

CALL BUSY

declined an incoming call from contact.

CALL ERROR err

failed to initiate or start outgoing call.

size is file size in bytes. Each FILE SEND message usually has a corresponding FILE RECV, FILE CANCEL or FILE REJECT message.

err (if present) is the same kind of error code which is returned everywhere else in the library. Each CALL START message usually has a corresponding CALL HANGUP or CALL HUNGUP message. CALL BUSY, CALL ABORT, CALL FAILED and CALL ERROR messages indicate events that did not succeed to start a call.

SIM_EVENT_NET. A network event of a specific type has occurred. Table keys:

SIM_EVENT_NET

string: event type is one of:

  • SIM_EVENT_NET_STATUS: network connection status has changed. One additional table key; id is zero
  • SIM_EVENT_NET_PONG: response to sim_contact_ping_. Two additional table keys (optional); id is non-zero
  • SIM_EVENT_NET_CONNECT: connected or failed to connect to contact. Three additional table keys; id is non-zero
  • SIM_EVENT_NET_DISCONNECT: disconnected from contact. One additional table key; id is non-zero
  • SIM_EVENT_NET_TRAVERSE: connection to contact is still relayed (connected through proxy) or no longer so (connected directly). Two additional table keys; id is non-zero
  • SIM_EVENT_NET_DEVICE: chosen audio device is invalid. Zero, one, two or three additional table keys; id is zero.

SIM_EVENT_NET_STATUS

number: network connection status (only if event type is SIM_EVENT_NET_STATUS). Positive if connected to the DHT, zero or negative if disconnected.

SIM_EVENT_NET_PONG

number: round-trip time in milliseconds (only if event type is SIM_EVENT_NET_PONG). Missing if not connected when pinging; zero means unknown.

SIM_EVENT_NET_PONG_NUMBER

number: number given to sim_contact_ping_(SIM_PING_BIT_TCP). Only if event type is SIM_EVENT_NET_PONG; missing if none.

SIM_EVENT_NET_CONNECT

number: error code or SIM_OK if successful (only if event type is SIM_EVENT_NET_CONNECT).

SIM_EVENT_NET_CONNECT_ENCRYPT

string: name of encrypt cipher (only if event type is SIM_EVENT_NET_CONNECT).

SIM_EVENT_NET_CONNECT_DECRYPT

string: name of decrypt cipher (only if event type is SIM_EVENT_NET_CONNECT).

SIM_EVENT_NET_DISCONNECT

number: error code or SIM_OK if normally disconnected (only if event type is SIM_EVENT_NET_DISCONNECT).

SIM_EVENT_NET_TRAVERSE

number: error code on failed NAT traversal or SIM_OK if connection no longer relayed (only if event type is SIM_EVENT_NET_TRAVERSE).

SIM_EVENT_NET_TRAVERSE_STATUS

string: traversal status (only if event type is SIM_EVENT_NET_TRAVERSE).

SIM_EVENT_NET_DEVICE_INPUT

string: name of invalid audio.input (only if event type is SIM_EVENT_NET_DEVICE). Missing if valid.

SIM_EVENT_NET_DEVICE_OUTPUT

string: name of invalid audio.output (only if event type is SIM_EVENT_NET_DEVICE). Missing if valid.

SIM_EVENT_NET_DEVICE_RING

string: name of invalid audio.ring (only if event type is SIM_EVENT_NET_DEVICE). Missing if valid.

SIM_EVENT_ERROR. An asynchronous error (that cannot be returned by an API function) has occurred. One or two table keys:

SIM_EVENT_ERROR

string: event type is one of:

  • SIM_EVENT_ERROR_SOCKS: cannot connect to socks proxy. One additional table key; id is zero
  • SIM_EVENT_ERROR_SYSTEM: contact is using an insecure operating system. One optional table key; id is non-zero
  • SIM_EVENT_ERROR_CIPHER: contact is using an undesired cipher (a soft warning). One optional table key; id is non-zero
  • SIM_EVENT_ERROR_PROTOCOL: possibly indicates a cryptographic attack on the network stream. One additional table key; id is non-zero
  • SIM_EVENT_ERROR_KEY: contact's public key does not match stored one (a hard error). No additional table keys; id is non-zero
  • SIM_EVENT_ERROR_XFER: file transfer warning. One additional table key; id is non-zero
  • SIM_EVENT_ERROR_AUDIO: audio call seems to have failed. One additional table key
  • SIM_EVENT_ERROR_INIT_LOCAL: cannot initialize localhost. One additional table key; id is zero
  • SIM_EVENT_ERROR_FILE_CREATE: cannot create file. One additional table key; id is non-zero
  • SIM_EVENT_ERROR_FILE_OPEN: cannot open file. One additional table key; id is non-zero
  • SIM_EVENT_ERROR_FILE_CLOSE: cannot close file. One additional table key; id is non-zero
  • SIM_EVENT_ERROR_FILE_LOAD: cannot load file. One additional table key
  • SIM_EVENT_ERROR_FILE_SAVE: cannot save file. One additional table key
  • SIM_EVENT_ERROR_FILE_WRITE: cannot write to file. One additional table key
  • SIM_EVENT_ERROR_FILE_DELETE: cannot delete file. One additional table key
  • SIM_EVENT_ERROR_FILE_WIPE: cannot wipe file. One additional table key
  • SIM_EVENT_ERROR_FILE_RENAME: cannot rename file. One additional table key
  • SIM_EVENT_ERROR_FILE_COPY: cannot copy file. One additional table key; id is zero.

SIM_EVENT_ERROR_SOCKS

number: socket error code (only if event type is SIM_EVENT_ERROR_SOCKS).

SIM_EVENT_ERROR_SYSTEM

string: name of the operating system (only if event type is SIM_EVENT_ERROR_SYSTEM). Missing if system is secure.

SIM_EVENT_ERROR_CIPHER

string: name of the undesired cipher (only if event type is SIM_EVENT_ERROR_CIPHER). Missing if cipher is desired.

SIM_EVENT_ERROR_PROTOCOL

number: crypto error code (SIM_CRYPT_BAD_TABLE, SIM_CRYPT_RSA_DECRYPT or SIM_CRYPT_RSA_VERIFY). Only if event type is SIM_EVENT_ERROR_PROTOCOL.

SIM_EVENT_ERROR_XFER

number: file transfer error code. Only if event type is SIM_EVENT_ERROR_XFER.

SIM_EVENT_ERROR_AUDIO

number: audio error code. Only if event type is SIM_EVENT_ERROR_AUDIO.

SIM_EVENT_ERROR_INIT_LOCAL

number: socket connect error code or SIM_SERVER_PORT. Only if event type is SIM_EVENT_ERROR_INIT_LOCAL.

SIM_EVENT_ERROR_FILE_CREATE

number: file error code. Only if event type is SIM_EVENT_ERROR_FILE_CREATE.

SIM_EVENT_ERROR_FILE_OPEN

number: file error code. Only if event type is SIM_EVENT_ERROR_FILE_OPEN.

SIM_EVENT_ERROR_FILE_CLOSE

number: file error code. Only if event type is SIM_EVENT_ERROR_FILE_CLOSE.

SIM_EVENT_ERROR_FILE_LOAD

number: file error code. Only if event type is SIM_EVENT_ERROR_FILE_LOAD.

SIM_EVENT_ERROR_FILE_SAVE

number: file error code. Only if event type is SIM_EVENT_ERROR_FILE_SAVE.

SIM_EVENT_ERROR_FILE_WRITE

number: file error code. Only if event type is SIM_EVENT_ERROR_FILE_WRITE.

SIM_EVENT_ERROR_FILE_DELETE

number: file error code. Only if event type is SIM_EVENT_ERROR_FILE_DELETE.

SIM_EVENT_ERROR_FILE_WIPE

number: file error code. Only if event type is SIM_EVENT_ERROR_FILE_WIPE.

SIM_EVENT_ERROR_FILE_RENAME

number: file error code. Only if event type is SIM_EVENT_ERROR_FILE_RENAME.

SIM_EVENT_ERROR_FILE_COPY

number: file error code. Only if event type is SIM_EVENT_ERROR_FILE_COPY.

SIM_EVENT_LOG. A new log line has been emitted; id is zero. Table key:

SIM_CMD_MSG_TEXT

string: log line in UTF-8 encoding (not including a terminating newline character).

SIM_EVENT_TICK. A CPU-intensive operation is taking place. One optional table key:

SIM_EVENT_TICK

string: identifies the function which sent the event.

When handling events, do not assume that the only table keys are the ones listed here. Also, a contact id which is always zero or always non-zero in the current version may change in future versions; always ensure it is not zero before you use it.

Event handlers (except for SIM_EVENT_FATAL and SIM_EVENT_TICK) should not block for a long time.

12. Utility Functions

const char *sim_error_get(int error);
const char *sim_error_peek(int error);

Return string which describes a given error code; the string is valid until the next call to the same function and CANNOT be freed by the caller.

A second invocation of sim_error_get might not report the same error string any more; if you need to call sim_error_get twice for the same error, call sim_error_peek instead of sim_error_get the first time.

These two functions return a pointer to a static buffer that contains the error string, so they are NOT thread-safe; you can call them only from a single thread of your choice.

const char *sim_error_get_buffer(int error, simbool peek, char output[SIM_SIZE_ERROR]);

Works just like sim_error_get or sim_error_peek but may use a user-supplied output buffer for the error string. It should be used when getting an error string from any other thread (not the thread of choice for sim_error_get and sim_error_peek). You can use sim_error_get_buffer with a single static output buffer in event handlers, as they are serialized.

Note the error string is available as a return value, which may or may not point to the user-supplied buffer.

void *sim_new(unsigned length);
void sim_free(void *pointer, unsigned length);

Work like malloc() and free() but may provide debug facilities. It is explicitly allowed to call sim_free with a NULL pointer and sim_new with a zero size. The same length given to sim_new should be given to sim_free; the latter overwrites the specified number of bytes with zeros before releasing memory.

To allow memory leak debugging, it is advisable to use sim_new and sim_free for all memory allocation needs. Do not give pointers returned by sim_new to free() or realloc(), and do not give pointers returned by standard library functions to sim_free.

simtype sim_convert_utf_to_int(const char *string, unsigned *length);
simtype sim_convert_int_to_utf(const int *string, unsigned *length);
simtype sim_convert_utf_to_ucs(const char *string, unsigned *length);
simtype sim_convert_ucs_to_utf(const unsigned short *string, unsigned *length);

Convert string from UTF-8 to UTF-32/UTF-16 or vice versa. length is an input-output argument; its value does not count the terminating zero. Return value points to the converted string, which the caller must release by calling sim_string_free. Return sim_nil (and zero *length) in case of an error (input does not have a valid encoding).

To access the returned string, cast sim_get_pointer with the returned simtype according to the following table:

function

return cast

input *length

output *length

sim_convert_utf_to_int   

int *   

number of bytes   

number of unicode characters

sim_convert_int_to_utf   

char *   

number of unicode characters   

number of bytes

sim_convert_utf_to_ucs   

unsigned short *   

number of bytes   

number of UTF-16 shorts

sim_convert_ucs_to_utf   

char *   

number of UTF-16 shorts   

number of bytes

Note sim_convert_ucs_to_utf accepts both little- and big-endian formats for any surrogate pairs of the input string, but if sim_convert_utf_to_ucs has to output surrogate pairs, they are in little-endian format ("trail" surrogate comes first, followed by "lead" surrogate). These two functions are mostly useful on Windows.

simtype sim_convert_type_to_json(const simtype value);

Return an ASCII string in "JSON" format, which has the contents of a given simtype (caller has to call sim_string_free to release the returned value when done with it). Works only with simtypes that do not contain binary data (only UTF-8 text, and no NUL characters), such as ones returned by API functions. Trying to convert a simtype that contains binary strings results in an "undefined" return value (binary strings are truncated at the first character that cannot be interpreted as UTF-8) but note sim_nil may be returned if the given simtype is completely invalid.

simtype sim_convert_type_to_xml(const simtype value, const char *tag);

Return an UTF-8 string in "XML" format, which has the contents of a given simtype or sim_nil if the simtype cannot be converted. If tag is NULL, no outer XML tag is written. Like sim_convert_type_to_json, it works only with simtypes that contain only UTF-8 text, but this is not checked and so binary simtypes would result in bad XML output. ASCII characters not valid in XML are replaced with spaces; the '&', '<' and '>' characters are escaped, as required by XML. Caller has to call sim_string_free to release the returned value when done with it.

simunsigned sim_get_tick(void);

Return number of milliseconds elapsed since an undefined but unchanging point in time (useful for programming of timeouts).

13. Debug Logging

The logger can output messages to the console, log file, and memory buffer. Each line has a:

Module name NULL outputs messages only to the console or memory.

void log_any_(const char *module, int level, const char *format, ...);

Log an UTF-8 message from the specified module at specified level.

void log_xtra_(const char *module, const char *format, ...);
void log_debug_(const char *module, const char *format, ...);
void log_info_(const char *module, const char *format, ...);
void log_note_(const char *module, const char *format, ...);
void log_warn_(const char *module, const char *format, ...);
void log_error_(const char *module, const char *format, ...);
void log_fatal_(const char *module, int error, const char *format, ...);

Log a message from the specified module at specific level.

For all logger functions, format is the same kind of format string that would be used with printf(). Use %lld for logging of simnumber and %llu for logging of simunsigned (even on Windows). The logged message can contain a newline character at the end but not anywhere else.

For log_fatal_, error must be SIM_OK.

simtype log_get_string_(simunsigned idx, simunsigned *datetime, const char **loglevel);

Read logged message with the given index. Indexes start at 1 and are guaranteed to remain the same until either sim_console_load_ or sim_exit_user_ is called.

The returned value is sim_nil if the given index is invalid or else it is a SIMPOINTER containing UTF-8 text; the data is guaranteed to remain accessible until either sim_console_load_ or sim_exit_user_ is called. Also returns time of the message as *datetime, which may be zero if message time is not available. The returned *loglevel is NULL if message has been emitted by the console.

simunsigned log_count_(void);

Return the highest log message index that can currently be given as an argument to log_get_string_. More log messages may arrive at any time.

int sim_console_load_(simnumber number);

Load the last number of messages from the log file (and unload all others). To clear the log buffer, call with zero number. To load the whole log file into the buffer, call with a very large number.

sim_console_load_ might block for a long time if there are many messages in the log file.

int sim_console_exec__(const char *command);

Execute a command as if it was typed at the console. If this function returns SIM_CONSOLE_QUIT_CMD, you should close the console immediately. Else it returns either SIM_OK or error code returned by the command. There is no guaranteed backwards-compatibility of console commands between different versions, so please refrain from using this function with predefined or automatically generated commands. It is meant to execute commands entered by a human user.

14. Additional Notes

The library has three main states:

Additionally, there are four locking levels:

The following table presents an overview of the states and locking levels in which each of the API functions can or cannot be called, as well as whether the functions are thread-safe.

functions

NONE

OUT

IN

LOCK

LOG

FATAL

thread-safe

sim_init_

 YES 

 -

 -

 NO 

 NO 

 NO 

 NO 

sim_init_user_

 NO 

 YES 

 -

 NO 

 NO 

 NO 

 YES 

sim_exit_user_

 NO 

 -

 YES 

 NO 

 NO 

 NO 

 YES 

sim_exit_

 -

 YES 

 YES 

 NO 

 NO 

 NO 

 NO 

sim_key_generate_

 NO 

 YES 

 -

 NO 

 NO 

 NO 

 YES 

sim_key_set_password_

 NO 

 -

 YES 

 NO 

 NO 

 NO 

 YES 

sim_event_register_

 NO 

 YES 

 YES 

 NO 

 NO 

 NO 

 YES 

sim_contact_xxx_, sim_status_xxx_

 NO 

 -

 YES 

 NO 

 NO 

 NO 

 YES 

sim_msg_xxx_, sim_xfer_xxx_

 NO 

 -

 YES 

 NO 

 NO 

 NO 

 YES 

sim_audio_xxx_, sim_sound_xxx_

 NO 

 YES 

 YES 

 NO 

 NO 

 NO 

 YES 

sim_param_xxx_, sim_list_info_

 NO 

 YES 

 YES 

 NO 

 NO 

 NO 

 YES 

sim_console_xxx_

 NO 

 YES 

 YES 

 NO 

 NO 

 NO 

 YES 

sim_list_versions, sim_list_free

 YES 

 YES 

 YES 

 YES 

 YES 

 NO 

 YES 

sim_error_get, sim_error_peek

 YES 

 YES 

 YES 

 YES 

 YES 

 YES 

 NO 

sim_error_get_buffer, sim_get_tick

 YES 

 YES 

 YES 

 YES 

 YES 

 YES 

 YES 

sim_new, sim_convert_xxx

 YES 

 YES 

 YES 

 YES 

 YES 

 NO 

 YES 

sim_free

 YES 

 YES 

 YES 

 YES 

 YES 

 YES 

 YES 

sim_string_xxx, sim_pointer_xxx

 YES 

 YES 

 YES 

 YES 

 YES 

 YES 

 YES 

sim_number_xxx, sim_nil

 YES 

 YES 

 YES 

 YES 

 YES 

 YES 

 YES 

sim_get_length, sim_get_type

 YES 

 YES 

 YES 

 YES 

 YES 

 YES 

 YES 

sim_table_xxx, sim_array_xxx

 YES 

 YES 

 YES 

 YES 

 YES 

 YES 

 YES 

log_xxx_

 -

 YES 

 YES 

 YES 

 NO 

 NO 

 YES 

The cells of the above table have the following meanings:

15. Compatibility

backwards-incompatible changes from 0.8 to 0.9.1