Newer
Older
/**
* TODO:
* 1. Add parsing for displaying APN profiles available to make sense of them
* 2. Add more input options when creating APN profile
* 3. Seperate "set default" and "apply" APN profiles (what is the difference anyway?)
* 4. Change way to seperate profile configurations? (i.e. currently 0: .., 1: .., n: ...)
#include "libmobile.h"
struct string {
char *ptr;
size_t len;
};
static void curl_cleaner(CURLcode *curl);
static size_t write_func(void *buffer, size_t size, size_t nmemb, void *userp);
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);
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 parsed here.
*
* Parameters:
* buffer - Contains chunk of response from server.
* size - Size (byte) of type in buffer array.
* nmemb - Number of members in buffer.
* userp - Pointer to area allocated for storing results from server.
*
* Returns:
* Number of bytes managed (size*nmemb).
*/
static size_t write_func(void *buffer, size_t size, size_t nmemb, void *userp)
{
struct string *str = (struct string *)userp;
size_t new_len = str->len + (size * nmemb);
str->ptr = realloc(str->ptr, new_len + 1);
if (str->ptr == NULL) {
printf("not enough ptr (realloc returned NULL)\n");
return 0;
}
memcpy(str->ptr + str->len, buffer, size * nmemb);
str->ptr[new_len] = '\0';
str->len = new_len;
return size * nmemb;
}
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) {
char *apn_profile = json_object_get_string(val);
Jakob Olsson
committed
if (!apn_profile || strlen(apn_profile) <= 0)
break;
char *apn_name = strtok(apn_profile, "($)");
if (strncmp(apn_name, name, 1024) == 0)
return idx;
idx++;
}
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)
char *response = mobile_get_apn_profiles();
Jakob Olsson
committed
if (!response) {
printf("no response!\n");
goto fail;
}
struct json_object *parsed_response = json_tokener_parse(response);
if(!parsed_response) {
printf("no valid json to parse!");
goto free_response;
}
Jakob Olsson
committed
json_object_object_foreach(parsed_response, key, val) {
Jakob Olsson
committed
goto success;
Jakob Olsson
committed
json_object_put(parsed_response);
free_response:
free(response);
fail:
Jakob Olsson
committed
success:
json_object_put(parsed_response);
free(response);
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) {
if(strlen(*input) == 0) {
printf("empty input!\n");
return NULL;
}
if(strlen(delimiter) == 0) {
printf("empty delimiter!\n");
return NULL;
}
char *token = strstr(*input, delimiter);
if (token)
*token = '\0';
char *substr = strdup(*input);
*input = token + strlen(delimiter);
return substr;
}
struct json_object *parse_apn_profiles(char *apn_profiles)
{
if (strlen(apn_profiles) <= 0) {
printf("No APN profiles provided!\n");
goto fail;
}
struct json_object *apn_profiles_json = json_tokener_parse(apn_profiles);
if (!apn_profiles_json) {
printf("Not valid json!\n");
goto fail;
}
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_json, key, val) {
struct json_object *apn_profile = json_object_new_object();
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);
char name[1024];
sprintf(name, "%d", apn_counter);
json_object_object_add(parsed_profiles, name, json_object_get(apn_profile));
json_object_put(apn_profile);
json_object_put(apn_profiles_json);
json_object_put(parsed_profiles);
fail:
return NULL;
finished:
json_object_put(apn_profiles_json);
return parsed_profiles;
}
char *mobile_connect_network(void)
return mobile_post_request("isTest=false&goformId=CONNECT_NETWORK");
char *mobile_disconnect_network(void)
return mobile_post_request("isTest=false&goformId=DISCONNECT_NETWORK");
Jakob Olsson
committed
char *mobile_delete_apn(char *name)
Jakob Olsson
committed
char *response = mobile_get_apn_profiles();
Jakob Olsson
committed
if (!response) {
printf("no response!\n");
goto fail;
}
struct json_object *parsed_response = json_tokener_parse(response);
if(!parsed_response) {
printf("no valid json to parse!");
goto free_response;
}
char query[1024] = {0};
int idx = apn_profile_idx(parsed_response, name);
Jakob Olsson
committed
if (idx < 0) {
printf("APN not found in list!\n");
Jakob Olsson
committed
goto free_all;
strncpy(query, "isTest=false&apn_action=delete&apn_mode=manual&index=", 1023);
sprintf(query + strlen(query), "%d", idx);
strncat(query + strlen(query), "&goformId=APN_PROC_EX", 1023);
Jakob Olsson
committed
json_object_put(parsed_response);
free(response);
return mobile_post_request(query);
Jakob Olsson
committed
free_all:
json_object_put(parsed_response);
free_response:
free(response);
Jakob Olsson
committed
fail:
return NULL;
char *mobile_enable_roaming(void)
return mobile_post_request("isTest=false&goformId=SET_CONNECTION_MODE&roam_setting_option=on");
}
char *mobile_disable_roaming(void)
{
return mobile_post_request("isTest=false&goformId=SET_CONNECTION_MODE&roam_setting_option=off");
}
char *mobile_get_roam_status(void)
{
return mobile_get_request("roam_setting_option");
}
char *mobile_get_wan_apn(void)
{
return mobile_get_request("wan_apn");
}
char *mobile_get_pinnumber(void)
{
return mobile_get_request("pinnumber");
}
char *mobile_get_pin_status(void)
{
return mobile_get_request("pin_status");
}
char *mobile_get_rssi(void)
{
return mobile_get_request("rssi");
}
char *mobile_get_modem_state(void)
{
return mobile_get_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");
}
char *mobile_get_apn_profiles(void)
{
return mobile_get_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");
Jakob Olsson
committed
char *mobile_create_apn_profile(char *name)
char query[1024] = {0};
strncpy(query, "isTest=false&goformId=APN_PROC_EX&apn_action=save&apn_mode=manual&profile_name=", 1023);
Jakob Olsson
committed
strncat(query + strlen(query), name, 1023);
strncat(query + strlen(query), "&wan_dial=*99%23&apn_select=manual&pdp_type=IP&pdp_select=auto&pdp_addr=&index=", 1023);
sprintf(query + strlen(query), "%d", get_apn_profiles_len());
strncat(query + strlen(query), "&wan_apn=", 1023);
Jakob Olsson
committed
strncat(query + strlen(query), name, 1023);
strncat(query + strlen(query), "&ppp_auth_mode=none&ppp_username=&ppp_passwd=&dns_mode=auto&prefer_dns_manual=&standby_dns_manual=", 1023);
return mobile_post_request(query);
Jakob Olsson
committed
char *mobile_set_apn_profile(char *name)
Jakob Olsson
committed
char *response = mobile_get_apn_profiles();
if (!response) {
printf("no response!\n");
goto fail;
}
struct json_object *parsed_response = json_tokener_parse(response);
if(!parsed_response) {
printf("no valid json to parse!");
goto free_response;
}
int idx = apn_profile_idx(parsed_response, name);
if (idx < 0) {
printf("couldnt find idx, no such profile!\n");
goto free_all;
}
char query[1024] = {0};
strncpy(query, "isTest=false&goformId=APN_PROC_EX&apn_mode=manual&apn_action=set_default&set_default_flag=1&pdp_type=IP&index=", 1023);
sprintf(query + strlen(query), "%d", idx);
Jakob Olsson
committed
json_object_put(parsed_response);
free(response);
return mobile_post_request(query);
Jakob Olsson
committed
free_all:
json_object_put(parsed_response);
free_response:
free(response);
fail:
return NULL;
char *mobile_enable_pin(char *pin)
{
char query[1024] = {0};
strncpy(query, "isTest=false&goformId=ENABLE_PIN&OldPinNumber=", 1023);
strncat(query + strlen(query), pin, 1023);
strncat(query + strlen(query), "&pin_save_flag=0&isTest=false", 1023);
return mobile_post_request(query);
char *mobile_set_pin(char *current_pin, char *new_pin)
char query[1024] = {0};
strncpy(query, "isTest=false&goformId=ENABLE_PIN&OldPinNumber=", 1023);
strncat(query + strlen(query), current_pin, 1023);
strncat(query + strlen(query), "&NewPinNumber=", 1023);
strncat(query + strlen(query), new_pin, 1023);
strncat(query + strlen(query), "&pin_save_flag=0&isTest=false", 1023);
return mobile_post_request(query);
char *mobile_disable_pin(char *pin)
char query[1024] = {0};
strncpy(query, "isTest=false&goformId=DISABLE_PIN&OldPinNumber=", 1023);
strncat(query + strlen(query), pin, 1023);
strncat(query + strlen(query), "&pin_save_flag=0&isTest=false", 1023);
return mobile_post_request(query);
char *mobile_post_request(char *query)
{
CURL *curl;
CURLcode res;
struct string str;
str.ptr = calloc(1, 1);
str.len = 0;
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.0.1/goform/goform_set_cmd_process");
curl_easy_setopt(curl, CURLOPT_REFERER, "http://192.168.0.1/index.html");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, query);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_func);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &str);
res = curl_easy_perform(curl);
printf("errored when performing curl, %s\n", curl_easy_strerror(res));
goto fail;
}
}
/**
* 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.
*/
char *get_query_wrapper(char *vars)
if (strlen(vars) == 0) {
printf("No GET input provided!\n");
return NULL;
}
char query[1024] = {0};
strncpy(query, "http://192.168.0.1/goform/goform_get_cmd_process?isTest=false&cmd=", 1023);
strncat(query + strlen(query), vars, 1023);
strncat(query + strlen(query), "&multi_data=1", 1023);
return strdup(query);
}
char *mobile_get_request(char *vars)
{
CURL *curl;
CURLcode res;
struct string str;
char *query = get_query_wrapper(vars);
if (!query)
goto fail;
str.ptr = calloc(1, 1);
str.len = 0;
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, query);
curl_easy_setopt(curl, CURLOPT_REFERER, "http://192.168.0.1/index.html");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_func);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &str);
res = curl_easy_perform(curl);
printf("errored when performing curl, %s\n", curl_easy_strerror(res));
goto fail;
}
}