Developer documentation

Backend services

The backend service is responsible for storing received messages and giving the SMSD core messages to send. It is solely up to them how the message will be stored, for example currently Gammu includes backends to store messages on filesystem (Files backend), various databases (MySQL Backend, PostgreSQL Backend, DBI Backend) or backend which does not store anything at all (Null Backend).

Backend interface

Each backend service needs to support several operations, which are exported in GSM_SMSDService structure:

GSM_Error GSM_SMSDService::Init(GSM_SMSDConfig *Config)

Initializes internal state, connect to backend storage.

Parameters:
  • Config – Pointer to SMSD configuration data
Returns:

Error code.

GSM_Error GSM_SMSDService::Free(GSM_SMSDConfig *Config)

Freeing internal data, disconnect from backend storage.

Parameters:
  • Config – Pointer to SMSD configuration data
Returns:

Error code.

GSM_Error GSM_SMSDService::InitAfterConnect(GSM_SMSDConfig *Config)

Optional hook called after SMSD is connected to phone, can be used for storing information about phone in backend.

Parameters:
  • Config – Pointer to SMSD configuration data
Returns:

Error code.

GSM_Error GSM_SMSDService::SaveInboxSMS(GSM_MultiSMSMessage *sms, GSM_SMSDConfig *Config, char **Locations)

Saves message into inbox.

Parameters:
  • sms – Message data to save
  • Config – Pointer to SMSD configuration data
  • Locations – Newly allocation pointer to string with IDs identifying saved messages.
Returns:

Error code.

GSM_Error GSM_SMSDService::FindOutboxSMS(GSM_MultiSMSMessage *sms, GSM_SMSDConfig *Config, char *ID)

Finds message in outbox suitable for sending.

Parameters:
  • sms – Found outbox message will be stored here
  • Config – Pointer to SMSD configuration data
  • ID – Identification of found message will be stored here, this should be unique for different message, so that repeated attempts to send same message can be detected by SMSD core. Empty string avoids this check.
Returns:

Error code.

GSM_Error GSM_SMSDService::MoveSMS(GSM_MultiSMSMessage *sms, GSM_SMSDConfig *Config, char *ID, gboolean alwaysDelete, gboolean sent)

Moves sent message from outbox to sent items.

Parameters:
  • sms – Message which should be moved, backend usually can get it by ID as well.
  • Config – Pointer to SMSD configuration data.
  • ID – Identification of message to be moved.
  • alwaysDelete – Whether to delete message from outbox even if moving fails.
  • sent – Whether message was sent (TRUE) or there was a failure (FALSE).
Returns:

Error code.

GSM_Error GSM_SMSDService::CreateOutboxSMS(GSM_MultiSMSMessage *sms, GSM_SMSDConfig *Config, char *NewID)

Saves message into outbox queue.

Parameters:
  • sms – Message data to save
  • Config – Pointer to SMSD configuration data
  • NewID – ID of created message will be stored here.
Returns:

Error code.

GSM_Error GSM_SMSDService::AddSentSMSInfo(GSM_MultiSMSMessage *sms, GSM_SMSDConfig *Config, char *ID, int Part, GSM_SMSDSendingError err, int TPMR)

Logs information about sent message (eg. delivery report).

Parameters:
  • sms – Message which should be moved, backend usually can get it by ID as well.
  • Config – Pointer to SMSD configuration data
  • ID – Identification of message to be marked.
  • Part – Part of the message which is being processed.
  • err – Status of sending message.
  • TPMR – Message reference if available (TPMR).
Returns:

Error code.

GSM_Error GSM_SMSDService::RefreshSendStatus(GSM_SMSDConfig *Config, char *ID)

Updates sending status in service backend.

Parameters:
  • Config – Pointer to SMSD configuration data
  • ID – Identification of message to be marked.
Returns:

Error code.

GSM_Error GSM_SMSDService::RefreshPhoneStatus(GSM_SMSDConfig *Config)

Updates information about phone in database (network status, battery, etc.).

Parameters:
  • Config – Pointer to SMSD configuration data
Returns:

Error code.

GSM_Error GSM_SMSDService::ReadConfiguration(GSM_SMSDConfig *Config)

Reads configuration specific for this backend.

Parameters:
  • Config – Pointer to SMSD configuration data
Returns:

Error code.

Message ID

You might have noticed that message ID is often used in the API. The primary reason for this is that it is usually easier for backend to handle message just by it’s internal identification instead of handling message data from GSM_MultiSMSMessage.

If the backend does not use any IDs internally, it really does not have to provide them, with only exception of GSM_SMSDService::FindOutboxSMS(), where ID is used for detection of repeated sending of same message.

The lifetime of ID for sent message:

The lifetime of ID for incoming messages:

Message Sending Workflow

digraph smsdsending { "new message" [shape=box]; "message in storage" [shape=box]; "message sent" [shape=box]; "error sending message" [shape=box]; "new message" -> "manually created SMS"; "new message" -> "CreateOutboxSMS"; "manually created SMS" -> "message in storage"; "CreateOutboxSMS" -> "message in storage" "message in storage" -> "FindOutboxSMS"; "FindOutboxSMS" -> "AddSentSMSInfo(ERROR)" [label="Error", style=dotted]; "FindOutboxSMS" -> "check duplicates"; "check duplicates" -> "AddSentSMSInfo(ERROR)" [label="Too many retries", style=dotted]; "check duplicates" -> "GSM_SendSMS"; "GSM_SendSMS" -> "RefreshSendStatus"; "GSM_SendSMS" -> "AddSentSMSInfo(ERROR)" [label="Error", style=dotted]; "RefreshSendStatus" -> "RefreshSendStatus" [label="Sending"]; "RefreshSendStatus" -> "AddSentSMSInfo(ERROR)" [label="Timeout", style=dotted]; "RefreshSendStatus" -> "AddSentSMSInfo(OK)"; "AddSentSMSInfo(OK)" -> "MoveSMS(noforce, OK)"; "MoveSMS(noforce, OK)" -> "MoveSMS(force, ERR)" [label="Error", style=dotted]; "AddSentSMSInfo(OK)" -> "MoveSMS(force, ERR)" [label="Error", style=dotted]; "AddSentSMSInfo(ERROR)" -> "MoveSMS(force, ERR)"; "MoveSMS(noforce, OK)" -> "message sent"; "MoveSMS(force, ERR)" -> "error sending message"; }

Message Receiving Workflow

digraph smsdreceiving { "received message" [shape=box]; "ignored message" [shape=box]; "failed message" [shape=box]; "waiting message" [shape=box]; "processed message" [shape=box]; "received message" -> "GSM_GetNextSMS"; "GSM_GetNextSMS" -> "SMSD_ValidMessage"; "SMSD_ValidMessage" -> "GSM_LinkSMS"; "SMSD_ValidMessage" -> "ignored message" [label="Not valid", style=dotted]; "GSM_LinkSMS" -> "SMSD_CheckMultipart"; "SMSD_CheckMultipart" -> "SaveInboxSMS"; "SMSD_CheckMultipart" -> "waiting message" [label="Not all parts", style=dotted]; "SaveInboxSMS" -> "SMSD_RunOnReceive" [label="Locations are passed here"]; "SaveInboxSMS" -> "failed message" [label="Error", style=dotted]; "SMSD_RunOnReceive" -> "GSM_DeleteSMS"; "GSM_DeleteSMS" -> "processed message" "GSM_DeleteSMS" -> "failed message" [label="Error", style=dotted]; }