Newer
Older
* 1. Add more input options when creating APN profile
* 2. Add DEBUG printout
#include "libmobile.h"
struct string {
char *ptr;
size_t len;
};
enum {
POST,
GET
};
char *referer_url = "http://192.168.0.1/index.html";
char *base_url = "http://192.168.0.1/goform/goform_set_cmd_process";
static void curl_cleaner(CURLcode *curl);
static size_t write_func(void *buffer, size_t size, size_t nmemb, void *data);
static int apn_profile_idx(struct json_object *apn_profiles, char *name);
static int get_apn_profiles_len(void);
static char *lexer(char **input, char *delimiter);
static char *get_query_wrapper(char *vars);
static CURLcode perform_post_request(CURL *curl, char *query, struct string *str);
static CURLcode perform_get_request(CURL *curl, char *query, struct string *str);
static struct json_object *prepare_request(char *query, int option);
static struct json_object *parse_apn_profiles(struct json_object *apn_profiles);
Jakob Olsson
committed
/**
* Function: curl_cleaner
*
* Free's the curl environment.
*
* Parameters:
* curl - The curl easy handle variable.
*/
static void curl_cleaner(CURLcode *curl)
{
curl_easy_cleanup(curl);
curl_global_cleanup();
}
Jakob Olsson
committed
/**
* Function: write_func
*
* The callback function from performing the curl command, response from server will be reconstructed here.
Jakob Olsson
committed
*
* Parameters:
* buffer - Contains chunk of response from server.
* size - Size (byte) of type in buffer array.
* nmemb - Number of members in buffer.
* data - Pointer to area allocated for storing results from server.
Jakob Olsson
committed
*
* Returns:
Jakob Olsson
committed
*/
static size_t write_func(void *buffer, size_t size, size_t nmemb, void *data)
struct string *str = (struct string *)data;
size_t new_len = str->len + (len);
char *tmp_ptr = str->ptr;
debug_print("not enough memory (realloc returned NULL)\n");
memcpy(str->ptr + str->len, buffer, len);
Jakob Olsson
committed
/**
* Function: apn_profile_idx
*
* Finds the index of a given profile name from all available profiles.
*
* Parameters:
* apn_profiles - json_object pointer to apn_profiles (gotten from a previous call to <mobile_get_apn_profiles>)
* name - Name of the APN index for which will be searched.
*
* Returns:
* Index of the APN on success.
* -1 on failure.
*/
static int apn_profile_idx(struct json_object *apn_profiles, char *name)
json_object_object_foreach(apn_profiles, key, val) {
Jakob Olsson
committed
struct json_object *profile_name_json;
Jakob Olsson
committed
json_object_object_get_ex(val, "profile_name", &profile_name_json);
Jakob Olsson
committed
if (!profile_name_json)
goto fail;
profile_name = json_object_get_string(profile_name_json);
Jakob Olsson
committed
if (strncmp(profile_name, name, 1024) == 0)
Jakob Olsson
committed
fail:
Jakob Olsson
committed
/**
* Function: get_apn_profiles_len
*
* Finds the number of APN profiles available.
*
* Returns:
* Number of APN profiles available on success.
* -1 on failure.
*/
static int get_apn_profiles_len(void)
struct json_object *apn_profiles = mobile_get_apn_profiles();
Jakob Olsson
committed
debug_print("Failed to get apn profiles from server!\n");
Jakob Olsson
committed
goto fail;
}
json_object_object_foreach(apn_profiles, key, val) {
int val_type = json_object_get_type(val);
if (val_type != json_type_string)
Jakob Olsson
committed
goto success;
Jakob Olsson
committed
success:
Jakob Olsson
committed
return len;
/**
* Function: lexer
*
* Take an input string and a delimiter which to split the string on. Returns all characters
* prior to the delimiter, and removes it from the input string.
*
* Parameters:
* input - A character pointer address to the pointer pointing at the string to split.
* delimiter - A character pointer pointing to the delimiter on which to split the string on.
*
* Returns:
* A character pointer to the tokens prior to the delimiter on success.
* NULL on failure, missing input, delimiter or when no delimiter is present.
*
* IMPORTANT NOTE
* Will alter the input string and allocate memory for the return value!
* The caller is responsible for freeing the return value.
*/
static char *lexer(char **input, char *delimiter)
{
debug_print("empty input!\n");
} else if (strlen(delimiter) == 0) {
debug_print("empty delimiter!\n");
token = strstr(*input, delimiter);
if (token)
*token = '\0';
*input = token + strlen(delimiter);
return substr;
}
/**
* Function: get_query_wrapper
* Wraps the input comma-separated values to the appropriate address format for a GET request.
*
* Parameters:
* vars - Char pointer pointing to comma-separated values to retreive.
*
* Returns:
* The entire query on success.
* NULL on failure.
*/
static char *get_query_wrapper(char *vars)
{
debug_print("No GET input provided!\n");
snprintf(query, 1023, "http://192.168.0.1/goform/goform_get_cmd_process?isTest=false&cmd=%s&multi_data=1", vars);
debug_print("query %s\n", query);
/**
* Function: perform_post_request
*
* Executes a prepared HTTP POST query through use of the libcurl lbirary.
*
* Parameter:
* curl - the CURL environment.
* query - The HTTP POST query to execute.
* str - a string struct containing the current data pointer and the length of the data currently written.
*
* Returns:
* The CURLcode indicating the success or failure of the curl execution.
*/
static CURLcode perform_post_request(CURL *curl, char *query, struct string *str)
{
curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.0.1/goform/goform_set_cmd_process");
//curl_easy_setopt(curl, CURLOPT_URL, base_url); //why doesn't this work?
curl_easy_setopt(curl, CURLOPT_REFERER, referer_url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, query);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_func);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, str);
return curl_easy_perform(curl);
}
/**
* Function: perform_get_request
*
* Executes a prepared HTTP GET query through use of the libcurl lbirary.
*
* Parameter:
* curl - the CURL environment.
* query - The HTTP GET query to execute.
* str - a string struct containing the current data pointer and the length of the data currently written.
*
* Returns:
* The CURLcode indicating the success or failure of the curl execution.
*/
static CURLcode perform_get_request(CURL *curl, char *query, struct string *str)
{
curl_easy_setopt(curl, CURLOPT_URL, query);
curl_easy_setopt(curl, CURLOPT_REFERER, referer_url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_func);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, str);
return curl_easy_perform(curl);
}
/**
* Function: send_post_request
*
* Function that prepares curl environment and final POST query, then executes said query.
*
* Parameter:
* query - The POST query content to execute.
*
* Returns:
* A pointer to a json_object containing the JSON response from the server.
* NULL on failure.
*/
static struct json_object *prepare_request(char *query, int option)
CURL *curl;
CURLcode rv;
struct string str = {NULL, 0};
struct json_object *parsed_response;
str.ptr = calloc(1, 1);
if (!str.ptr) {
debug_print("Error allocating memory with calloc");
curl = curl_easy_init();
if (!curl) {
debug_print("Failed to prepare curl environment!\n");
if (option == POST)
rv = perform_post_request(curl, query, &str);
else if (option == GET) {
query = get_query_wrapper(query);
rv = perform_get_request(curl, query, &str);
}
debug_print("error performing curl, %s\n", curl_easy_strerror(rv));
if (!str.ptr)
goto fail_ptr;
debug_print("%s\n", str.ptr);
parsed_response = json_tokener_parse(str.ptr);
debug_print("No valid JSON, failed parsing!\n");
goto fail_json;
}
free(query);
curl_cleaner(curl);
free(str.ptr);
return parsed_response;
fail_json:
fail_ptr:
curl_cleaner(curl);
fail_curl:
free(str.ptr);
fail:
free(query);
return NULL;
}
/**
* Function: parse_apn_profiles
*
* Takes a string of APN profile configurations provided by zte-mf823 (which is in an awkward, difficult to read format)
* and transforms them into a more easily read and worked with JSON format.
*
* Parameters:
* apn_profiles - A json_object pointer containing the original apn configuration returned by the dongle.
* A json_object pointer to apn configurations in a more representative and easier to use format.
static struct json_object *parse_apn_profiles(struct json_object *apn_profiles)
struct json_object *parsed_profiles = json_object_new_object();
char *field_names[13] = {"profile_name", "apn_name", "mode", "wan_dial", "ppp_auth_mode", "ppp_username", "ppp_passwd", "pdp", "pdpd_select", "pdp_addr", "dns_mode", "prefer_dns_manual", "standby_dns_manual"};
json_object_object_foreach(apn_profiles, key, val) {
struct json_object *apn_profile = json_object_new_object();
if (strlen(apn_string) <= 0)
goto finished;
while ((field_val = lexer(&apn_string, "($)")) != NULL) {
json_object_object_add(apn_profile, field_names[i], json_object_new_string(field_val));
i++;
free(field_val);
snprintf(name, 1023, "apn_config_%d", apn_counter);
json_object_object_add(parsed_profiles, name, json_object_get(apn_profile));
json_object_put(apn_profile);
return parsed_profiles;
}
struct json_object *mobile_connect_network(void)
return prepare_request("isTest=false&goformId=CONNECT_NETWORK", POST);
struct json_object *mobile_disconnect_network(void)
return prepare_request("isTest=false&goformId=DISCONNECT_NETWORK", POST);
struct json_object *mobile_delete_apn(char *name)
struct json_object *apn_profiles = mobile_get_apn_profiles();
char query[1024] = {0};
int idx;
debug_print("no response!\n");
Jakob Olsson
committed
goto fail;
}
idx = apn_profile_idx(apn_profiles, name);
if (idx < 0) {
debug_print("APN not found in list!\n");
snprintf(query, 1023, "isTest=false&apn_action=delete&apn_mode=manual&index=%d&goformId=APN_PROC_EX", idx);
return prepare_request(query, POST);
Jakob Olsson
committed
fail_idx:
json_object_put(apn_profiles);
Jakob Olsson
committed
fail:
return NULL;
struct json_object *mobile_enable_roaming(void)
return prepare_request("isTest=false&goformId=SET_CONNECTION_MODE&roam_setting_option=on", POST);
struct json_object *mobile_disable_roaming(void)
return prepare_request("isTest=false&goformId=SET_CONNECTION_MODE&roam_setting_option=off", POST);
struct json_object *mobile_get_roam_status(void)
return prepare_request("roam_setting_option", GET);
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
struct json_object *mobile_get_current_apn(void)
{
struct json_object *idx_json, *apn_profiles, *tmp, *current_profile;
int idx, counter = 0;
idx_json = prepare_request("Current_index", GET);
if (!idx_json) {
debug_print("couldn't find index\n");
goto fail;
}
//tmp = json_object_object_get_ex(idx_json, "Current_index", &tmp);
idx = json_object_get_int(idx_json);
if (idx < 0 || idx > 9) {
debug_print("Something is very wrong!\n");
goto fail_idx;
}
apn_profiles = mobile_get_apn_profiles();
json_object_object_foreach(apn_profiles, key, val) {
counter++;
if (counter < idx)
continue;
current_profile = json_object_get(val);
break;
}
json_object_put_(idx_json);
json_object_put(apn_profiles);
return current_profile;
fail_idx:
json_object_put(idx_json);
fail:
return NULL;
}
struct json_object *mobile_get_wan_apn(void)
return prepare_request("wan_apn", GET);
struct json_object *mobile_get_remaining_tries(void)
return prepare_request("pinnumber", GET);
struct json_object *mobile_get_pin_status(void)
return prepare_request("pin_status", GET);
struct json_object *mobile_get_rssi(void)
return prepare_request("rssi", GET);
struct json_object *mobile_get_modem_state(void)
return prepare_request("&sms_received_flag_flag=0&sts_received_flag_flag=0&cmd=modem_main_state%2Cpin_status%2Cloginfo%2Cnew_version_state%2Ccurrent_upgrade_state%2Cis_mandatory%2Csms_received_flag%2Csts_received_flag%2Csignalbar%2Cnetwork_type%2Cnetwork_provider%2Cppp_status%2CEX_SSID1%2Cex_wifi_status%2CEX_wifi_profile%2Cm_ssid_enable%2Csms_unread_num%2CRadioOff%2Csimcard_roam%2Clan_ipaddr%2Cstation_mac%2Cbattery_charging%2Cbattery_vol_percent%2Cbattery_pers%2Cspn_display_flag%2Cplmn_display_flag%2Cspn_name_data%2Cspn_b1_flag%2Cspn_b2_flag%2Crealtime_tx_bytes%2Crealtime_rx_bytes%2Crealtime_time%2Crealtime_tx_thrpt%2Crealtime_rx_thrpt%2Cmonthly_rx_bytes%2Cmonthly_tx_bytes%2Cmonthly_time%2Cdate_month%2Cdata_volume_limit_switch%2Cdata_volume_limit_size%2Cdata_volume_alert_percent%2Cdata_volume_limit_unit%2Croam_setting_option%2Cupg_roam_switch%2Chplmn", GET);
struct json_object *mobile_get_apn_profiles(void)
struct json_object *apn_profiles = prepare_request("APN_config0,APN_config1,APN_config2,APN_config3,APN_config4,APN_config5,APN_config6,APN_config7,APN_config8,APN_config9,APN_config10,APN_config11,APN_config12,APN_config13,APN_config14,APN_config15,APN_config16,APN_config17,APN_config18,APN_config19", GET);
debug_print("Error getting profiles!\n");
return parse_apn_profiles(apn_profiles);
Jakob Olsson
committed
struct json_object *mobile_create_apn_profile(char *profile_name, char *wan_apn, char *pdp_type)
char query[1024] = {0};
snprintf(query, 1023, "isTest=false&goformId=APN_PROC_EX&apn_action=save&apn_mode=manual&profile_name=%s&wan_dial=*99%23&apn_select=manual&pdp_type=%s&pdp_select=auto&pdp_addr=&index=%d&wan_apn=%s&ppp_auth_mode=none&ppp_username=&ppp_passwd=&dns_mode=auto&prefer_dns_manual=&standby_dns_manual=", profile_name, pdp_type, get_apn_profiles_len(), wan_apn);
Jakob Olsson
committed
return prepare_request(query, POST);
struct json_object *mobile_set_apn_profile(char *name)
struct json_object *apn_profiles = mobile_get_apn_profiles();
int idx;
char query[1024] = {0};
Jakob Olsson
committed
debug_print("no response!\n");
Jakob Olsson
committed
goto fail;
}
idx = apn_profile_idx(apn_profiles, name);
Jakob Olsson
committed
if (idx < 0) {
debug_print("couldnt find idx, no such profile!\n");
Jakob Olsson
committed
}
snprintf(query, 1023, "isTest=false&goformId=APN_PROC_EX&apn_mode=manual&apn_action=set_default&set_default_flag=1&pdp_type=IP&index=%d", idx);
return prepare_request(query, POST);
free_idx:
json_object_put(apn_profiles);
Jakob Olsson
committed
fail:
return NULL;
struct json_object *mobile_enable_pin(char *pin)
{
char query[1024] = {0};
snprintf(query, 1023, "isTest=false&goformId=ENABLE_PIN&OldPinNumber=%s&pin_save_flag=0&isTest=false", pin);
return prepare_request(query, POST);
struct json_object *mobile_set_pin(char *current_pin, char *new_pin)
char query[1024] = {0};
snprintf(query, 1023, "isTest=false&goformId=ENABLE_PIN&OldPinNumber=%s&NewPinNumber=%s&pin_save_flag=0&isTest=false", current_pin, new_pin);
return prepare_request(query, POST);
struct json_object *mobile_disable_pin(char *pin)
char query[1024] = {0};
snprintf(query, 1023, "isTest=false&goformId=DISABLE_PIN&OldPinNumber=%s&pin_save_flag=0&isTest=false", pin);
return prepare_request(query, POST);