static struct ast_manager_event_blob *peerstatus_to_ami(struct stasis_message *msg) { struct ast_endpoint_blob *obj = stasis_message_data(msg); RAII_VAR(struct ast_str *, peerstatus_event_string, ast_str_create(64), ast_free); const char *value; /* peer_status is the only *required* thing */ if (!(value = ast_json_string_get(ast_json_object_get(obj->blob, "peer_status")))) { return NULL; } ast_str_append(&peerstatus_event_string, 0, "PeerStatus: %s\r\n", value); if ((value = ast_json_string_get(ast_json_object_get(obj->blob, "cause")))) { ast_str_append(&peerstatus_event_string, 0, "Cause: %s\r\n", value); } if ((value = ast_json_string_get(ast_json_object_get(obj->blob, "address")))) { ast_str_append(&peerstatus_event_string, 0, "Address: %s\r\n", value); } if ((value = ast_json_string_get(ast_json_object_get(obj->blob, "port")))) { ast_str_append(&peerstatus_event_string, 0, "Port: %s\r\n", value); } if ((value = ast_json_string_get(ast_json_object_get(obj->blob, "time")))) { ast_str_append(&peerstatus_event_string, 0, "Time: %s\r\n", value); } return ast_manager_event_blob_create(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: %s\r\n" "Peer: %s/%s\r\n" "%s", obj->snapshot->tech, obj->snapshot->tech, obj->snapshot->resource, ast_str_buffer(peerstatus_event_string)); }
static struct ast_manager_event_blob *varset_to_ami(struct stasis_message *msg) { RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free); struct ast_channel_blob *obj = stasis_message_data(msg); const char *variable = ast_json_string_get(ast_json_object_get(obj->blob, "variable")); const char *value = ast_json_string_get(ast_json_object_get(obj->blob, "value")); if (obj->snapshot) { channel_event_string = ast_manager_build_channel_state_string(obj->snapshot); } else { channel_event_string = ast_str_create(35); ast_str_set(&channel_event_string, 0, "Channel: none\r\n" "Uniqueid: none\r\n"); } if (!channel_event_string) { return NULL; } return ast_manager_event_blob_create(EVENT_FLAG_DIALPLAN, "VarSet", "%s" "Variable: %s\r\n" "Value: %s\r\n", ast_str_buffer(channel_event_string), variable, value); }
/*! * \brief Callback handler for Stasis application messages. */ static void app_handler(void *data, const char *app_name, struct ast_json *message) { struct event_session *session = data; int res; const char *msg_type = S_OR( ast_json_string_get(ast_json_object_get(message, "type")), ""); const char *msg_application = S_OR( ast_json_string_get(ast_json_object_get(message, "application")), ""); /* Determine if we've been replaced */ if (strcmp(msg_type, "ApplicationReplaced") == 0 && strcmp(msg_application, app_name) == 0) { ao2_find(session->websocket_apps, msg_application, OBJ_UNLINK | OBJ_NODATA); } res = ast_json_object_set(message, "application", ast_json_string_create(app_name)); if(res != 0) { return; } ao2_lock(session); if (session->ws_session) { ast_ari_websocket_session_write(session->ws_session, message); } ao2_unlock(session); }
static struct ast_manager_event_blob *system_registry_to_ami(struct stasis_message *message) { struct ast_json_payload *payload = stasis_message_data(message); const char *channeltype; const char *username; const char *domain; const char *status; const char *cause; RAII_VAR(struct ast_str *, cause_string, ast_str_create(32), ast_free); if (!cause_string) { return NULL; } channeltype = ast_json_string_get(ast_json_object_get(payload->json, "channeltype")); username = ast_json_string_get(ast_json_object_get(payload->json, "username")); domain = ast_json_string_get(ast_json_object_get(payload->json, "domain")); status = ast_json_string_get(ast_json_object_get(payload->json, "status")); cause = ast_json_string_get(ast_json_object_get(payload->json, "cause")); if (!ast_strlen_zero(cause)) { ast_str_set(&cause_string, 0, "Cause: %s\r\n", cause); } return ast_manager_event_blob_create(EVENT_FLAG_SYSTEM, "Registry", "ChannelType: %s\r\n" "Username: %s\r\n" "Domain: %s\r\n" "Status: %s\r\n" "%s", channeltype, username, domain, status, ast_str_buffer(cause_string)); }
static struct ast_manager_event_blob *contactstatus_to_ami(struct stasis_message *msg) { struct ast_endpoint_blob *obj = stasis_message_data(msg); RAII_VAR(struct ast_str *, contactstatus_event_string, ast_str_create(64), ast_free); const char *value; if (!(value = ast_json_string_get(ast_json_object_get(obj->blob, "uri")))) { return NULL; } ast_str_append(&contactstatus_event_string, 0, "URI: %s\r\n", value); if (!(value = ast_json_string_get(ast_json_object_get(obj->blob, "contact_status")))) { return NULL; } ast_str_append(&contactstatus_event_string, 0, "ContactStatus: %s\r\n", value); if (!(value = ast_json_string_get(ast_json_object_get(obj->blob, "aor")))) { return NULL; } ast_str_append(&contactstatus_event_string, 0, "AOR: %s\r\n", value); if (!(value = ast_json_string_get(ast_json_object_get(obj->blob, "endpoint_name")))) { return NULL; } ast_str_append(&contactstatus_event_string, 0, "EndpointName: %s\r\n", value); if ((value = ast_json_string_get(ast_json_object_get(obj->blob, "roundtrip_usec")))) { ast_str_append(&contactstatus_event_string, 0, "RoundtripUsec: %s\r\n", value); } return ast_manager_event_blob_create(EVENT_FLAG_SYSTEM, "ContactStatus", "%s", ast_str_buffer(contactstatus_event_string)); }
static struct ast_json *contactstatus_to_json(struct stasis_message *msg, const struct stasis_message_sanitizer *sanitize) { struct ast_endpoint_blob *obj = stasis_message_data(msg); struct ast_json *json_endpoint; struct ast_json *json_final; const struct timeval *tv = stasis_message_timestamp(msg); json_endpoint = ast_endpoint_snapshot_to_json(obj->snapshot, NULL); if (!json_endpoint) { return NULL; } json_final = ast_json_pack("{s: s, s: o, s: o, s: { s: s, s: s, s: s, s: s } } ", "type", "ContactStatusChange", "timestamp", ast_json_timeval(*tv, NULL), "endpoint", json_endpoint, "contact_info", "uri", ast_json_string_get(ast_json_object_get(obj->blob, "uri")), "contact_status", ast_json_string_get(ast_json_object_get(obj->blob, "contact_status")), "aor", ast_json_string_get(ast_json_object_get(obj->blob, "aor")), "roundtrip_usec", ast_json_string_get(ast_json_object_get(obj->blob, "roundtrip_usec"))); if (!json_final) { ast_json_unref(json_endpoint); } return json_final; }
int create_queue(struct ast_json* j_queue) { int ret; char* uuid; struct ast_json* j_tmp; if(j_queue == NULL) { return false; } j_tmp = ast_json_deep_copy(j_queue); uuid = gen_uuid(); ast_json_object_set(j_tmp, "uuid", ast_json_string_create(uuid)); ast_log(LOG_NOTICE, "Create queue. uuid[%s], name[%s]\n", ast_json_string_get(ast_json_object_get(j_tmp, "uuid")), ast_json_string_get(ast_json_object_get(j_tmp, "name")) ); ret = db_insert("queue", j_tmp); AST_JSON_UNREF(j_tmp); if(ret == false) { ast_free(uuid); return false; } // send ami event j_tmp = get_queue(uuid); send_manager_evt_out_queue_create(j_tmp); AST_JSON_UNREF(j_tmp); return true; }
/*! \brief Generic MWI event callback used for one-off events from voicemail modules */ static void mwi_app_event_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message) { struct ast_mwi_blob *payload = stasis_message_data(message); RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free); RAII_VAR(struct ast_str *, event_buffer, NULL, ast_free); struct ast_json *event_json = ast_json_object_get(payload->blob, "Event"); if (!event_json) { return; } if (payload->mwi_state && payload->mwi_state->snapshot) { channel_event_string = ast_manager_build_channel_state_string(payload->mwi_state->snapshot); } event_buffer = ast_manager_str_from_json_object(payload->blob, exclude_event_cb); if (!event_buffer) { ast_log(AST_LOG_WARNING, "Failed to create payload for event %s\n", ast_json_string_get(event_json)); return; } manager_event(EVENT_FLAG_CALL, ast_json_string_get(event_json), "Mailbox: %s\r\n" "%s" "%s", payload->mwi_state ? payload->mwi_state->uniqueid : "Unknown", ast_str_buffer(event_buffer), channel_event_string ? ast_str_buffer(channel_event_string) : ""); }
int ast_ari_bridges_play_parse_body( struct ast_json *body, struct ast_ari_bridges_play_args *args) { struct ast_json *field; /* Parse query parameters out of it */ field = ast_json_object_get(body, "media"); if (field) { args->media = ast_json_string_get(field); } field = ast_json_object_get(body, "lang"); if (field) { args->lang = ast_json_string_get(field); } field = ast_json_object_get(body, "offsetms"); if (field) { args->offsetms = ast_json_integer_get(field); } field = ast_json_object_get(body, "skipms"); if (field) { args->skipms = ast_json_integer_get(field); } field = ast_json_object_get(body, "playbackId"); if (field) { args->playback_id = ast_json_string_get(field); } return 0; }
static struct ast_json *dtmf_end_to_json( struct stasis_message *message, const struct stasis_message_sanitizer *sanitize) { struct ast_channel_blob *channel_blob = stasis_message_data(message); struct ast_json *blob = channel_blob->blob; struct ast_channel_snapshot *snapshot = channel_blob->snapshot; const char *direction = ast_json_string_get(ast_json_object_get(blob, "direction")); const struct timeval *tv = stasis_message_timestamp(message); struct ast_json *json_channel = ast_channel_snapshot_to_json(snapshot, sanitize); /* Only present received DTMF end events as JSON */ if (strcasecmp("Received", direction) != 0) { return NULL; } if (!json_channel) { return NULL; } return ast_json_pack("{s: s, s: o, s: O, s: O, s: o}", "type", "ChannelDtmfReceived", "timestamp", ast_json_timeval(*tv, NULL), "digit", ast_json_object_get(blob, "digit"), "duration_ms", ast_json_object_get(blob, "duration_ms"), "channel", json_channel); }
static void confbridge_publish_manager_event( struct stasis_message *message, const char *event, struct ast_str *extra_text) { struct ast_bridge_blob *blob = stasis_message_data(message); const char *conference_name; RAII_VAR(struct ast_str *, bridge_text, NULL, ast_free); RAII_VAR(struct ast_str *, channel_text, NULL, ast_free); ast_assert(blob != NULL); ast_assert(event != NULL); bridge_text = ast_manager_build_bridge_state_string(blob->bridge); if (!bridge_text) { return; } conference_name = ast_json_string_get(ast_json_object_get(blob->blob, "conference")); ast_assert(conference_name != NULL); if (blob->channel) { channel_text = ast_manager_build_channel_state_string(blob->channel); } manager_event(EVENT_FLAG_CALL, event, "Conference: %s\r\n" "%s" "%s" "%s", conference_name, ast_str_buffer(bridge_text), S_COR(channel_text, ast_str_buffer(channel_text), ""), S_COR(extra_text, ast_str_buffer(extra_text), "")); }
int ast_json_to_ast_variables(struct ast_json *json_variables, struct ast_variable **variables) { struct ast_json_iter *it_json_var; *variables = NULL; for (it_json_var = ast_json_object_iter(json_variables); it_json_var; it_json_var = ast_json_object_iter_next(json_variables, it_json_var)) { struct ast_variable *new_var; const char *key = ast_json_object_iter_key(it_json_var); if (ast_strlen_zero(key)) { continue; } new_var = ast_variable_new(key, ast_json_string_get(ast_json_object_iter_value(it_json_var)), ""); if (!new_var) { ast_variables_destroy(*variables); *variables = NULL; return -1; } ast_variable_list_append(variables, new_var); } return 0; }
int ast_ari_endpoints_send_message_to_endpoint_parse_body( struct ast_json *body, struct ast_ari_endpoints_send_message_to_endpoint_args *args) { struct ast_json *field; /* Parse query parameters out of it */ field = ast_json_object_get(body, "from"); if (field) { args->from = ast_json_string_get(field); } field = ast_json_object_get(body, "body"); if (field) { args->body = ast_json_string_get(field); } return 0; }
/*! * \brief Send a message to the given application. * \param app App to send the message to. * \param message Message to send. */ void app_send(struct stasis_app *app, struct ast_json *message) { stasis_app_cb handler; char eid[20]; RAII_VAR(void *, data, NULL, ao2_cleanup); if (ast_json_object_set(message, "asterisk_id", ast_json_string_create( ast_eid_to_str(eid, sizeof(eid), &ast_eid_default)))) { ast_log(AST_LOG_WARNING, "Failed to append EID to outgoing event %s\n", ast_json_string_get(ast_json_object_get(message, "type"))); } /* Copy off mutable state with lock held */ { SCOPED_AO2LOCK(lock, app); handler = app->handler; if (app->data) { ao2_ref(app->data, +1); data = app->data; } /* Name is immutable; no need to copy */ } if (!handler) { ast_verb(3, "Inactive Stasis app '%s' missed message\n", app->name); return; } handler(data, app->name, message); }
int ast_ari_asterisk_set_global_var_parse_body( struct ast_json *body, struct ast_ari_asterisk_set_global_var_args *args) { struct ast_json *field; /* Parse query parameters out of it */ field = ast_json_object_get(body, "variable"); if (field) { args->variable = ast_json_string_get(field); } field = ast_json_object_get(body, "value"); if (field) { args->value = ast_json_string_get(field); } return 0; }
int ast_ari_bridges_create_with_id_parse_body( struct ast_json *body, struct ast_ari_bridges_create_with_id_args *args) { struct ast_json *field; /* Parse query parameters out of it */ field = ast_json_object_get(body, "type"); if (field) { args->type = ast_json_string_get(field); } field = ast_json_object_get(body, "name"); if (field) { args->name = ast_json_string_get(field); } return 0; }
static int json_to_ast_variables(struct ast_json *json_variables, struct ast_variable **variables) { struct ast_variable *current = NULL; struct ast_json_iter *it_json_var; for (it_json_var = ast_json_object_iter(json_variables); it_json_var; it_json_var = ast_json_object_iter_next(json_variables, it_json_var)) { struct ast_variable *new_var; new_var = ast_variable_new(ast_json_object_iter_key(it_json_var), ast_json_string_get(ast_json_object_iter_value(it_json_var)), ""); if (!new_var) { ast_variables_destroy(*variables); *variables = NULL; return 1; } if (!current) { *variables = new_var; current = *variables; } else { current->next = new_var; current = new_var; } } return 0; }
static void channel_enter_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message) { static const char *swap_name = "SwapUniqueid: "; struct ast_bridge_blob *blob = stasis_message_data(message); RAII_VAR(struct ast_str *, bridge_text, NULL, ast_free); RAII_VAR(struct ast_str *, channel_text, NULL, ast_free); const char *swap_id; bridge_text = ast_manager_build_bridge_state_string(blob->bridge); channel_text = ast_manager_build_channel_state_string(blob->channel); if (!bridge_text || !channel_text) { return; } swap_id = ast_json_string_get(ast_json_object_get(blob->blob, "swap")); manager_event(EVENT_FLAG_CALL, "BridgeEnter", "%s" "%s" "%s%s%s", ast_str_buffer(bridge_text), ast_str_buffer(channel_text), swap_id ? swap_name : "", S_OR(swap_id, ""), swap_id ? "\r\n" : ""); }
/*! * \brief Send a message to the given application. * \param app App to send the message to. * \param message Message to send. */ void app_send(struct stasis_app *app, struct ast_json *message) { stasis_app_cb handler; char eid[20]; void *data; if (ast_json_object_set(message, "asterisk_id", ast_json_string_create( ast_eid_to_str(eid, sizeof(eid), &ast_eid_default)))) { ast_log(AST_LOG_WARNING, "Failed to append EID to outgoing event %s\n", ast_json_string_get(ast_json_object_get(message, "type"))); } /* Copy off mutable state with lock held */ ao2_lock(app); handler = app->handler; data = ao2_bump(app->data); ao2_unlock(app); /* Name is immutable; no need to copy */ if (handler) { handler(data, app->name, message); } else { ast_verb(3, "Inactive Stasis app '%s' missed message\n", app->name); } ao2_cleanup(data); }
int ast_ari_sounds_list_parse_body( struct ast_json *body, struct ast_ari_sounds_list_args *args) { struct ast_json *field; /* Parse query parameters out of it */ field = ast_json_object_get(body, "lang"); if (field) { args->lang = ast_json_string_get(field); } field = ast_json_object_get(body, "format"); if (field) { args->format = ast_json_string_get(field); } return 0; }
static struct ast_manager_event_blob *cc_available_to_ami(struct stasis_message *message) { struct ast_json_payload *payload = stasis_message_data(message); int core_id; const char *callee; const char *service; core_id = ast_json_integer_get(ast_json_object_get(payload->json, "core_id")); callee = ast_json_string_get(ast_json_object_get(payload->json, "callee")); service = ast_json_string_get(ast_json_object_get(payload->json, "service")); return ast_manager_event_blob_create(EVENT_FLAG_CC, "CCAvailable", "CoreID: %d\r\n" "Callee: %s\r\n" "Service: %s\r\n", core_id, callee, service); }
static struct ast_manager_event_blob *cc_requested_to_ami(struct stasis_message *message) { struct ast_json_payload *payload = stasis_message_data(message); int core_id; const char *caller; const char *callee; core_id = ast_json_integer_get(ast_json_object_get(payload->json, "core_id")); caller = ast_json_string_get(ast_json_object_get(payload->json, "caller")); callee = ast_json_string_get(ast_json_object_get(payload->json, "callee")); return ast_manager_event_blob_create(EVENT_FLAG_CC, "CCRequested", "CoreID: %d\r\n" "Caller: %s\r\n" "Callee: %s\r\n", core_id, caller, callee); }
/** * Create plan. * @param j_plan * @return */ bool create_plan(const struct ast_json* j_plan) { int ret; char* uuid; struct ast_json* j_tmp; char* tmp; if(j_plan == NULL) { return false; } j_tmp = ast_json_deep_copy(j_plan); uuid = gen_uuid(); ast_json_object_set(j_tmp, "uuid", ast_json_string_create(uuid)); tmp = get_utc_timestamp(); ast_json_object_set(j_tmp, "tm_create", ast_json_string_create(tmp)); ast_free(tmp); ast_log(LOG_NOTICE, "Create plan. uuid[%s], name[%s]\n", ast_json_string_get(ast_json_object_get(j_tmp, "uuid")), ast_json_string_get(ast_json_object_get(j_tmp, "name"))? : "<unknown>" ); ret = db_insert("plan", j_tmp); AST_JSON_UNREF(j_tmp); if(ret == false) { ast_free(uuid); return false; } ast_log(LOG_VERBOSE, "Finished insert.\n"); // send ami event j_tmp = get_plan(uuid); ast_log(LOG_VERBOSE, "Check plan info. uuid[%s]\n", ast_json_string_get(ast_json_object_get(j_tmp, "uuid")) ); ast_free(uuid); if(j_tmp == NULL) { ast_log(LOG_ERROR, "Could not get created plan info."); return false; } send_manager_evt_out_plan_create(j_tmp); AST_JSON_UNREF(j_tmp); return true; }
static struct ast_manager_event_blob *cc_failure_to_ami(struct stasis_message *message) { struct ast_json_payload *payload = stasis_message_data(message); int core_id; const char *caller; const char *reason; core_id = ast_json_integer_get(ast_json_object_get(payload->json, "core_id")); caller = ast_json_string_get(ast_json_object_get(payload->json, "caller")); reason = ast_json_string_get(ast_json_object_get(payload->json, "reason")); return ast_manager_event_blob_create(EVENT_FLAG_CC, "CCFailure", "CoreID: %d\r\n" "Caller: %s\r\n" "Reason: %s\r\n", core_id, caller, reason); }
/*! * \brief Callback handler for Stasis application messages. * * \internal * * \param data Void pointer to the event session (\ref event_session). * \param app_name Name of the Stasis application that dispatched the message. * \param message The dispatched message. */ static void stasis_app_message_handler( void *data, const char *app_name, struct ast_json *message) { struct event_session *session = data; const char *msg_type, *msg_application; ast_assert(session != NULL); ao2_lock(session); msg_type = S_OR(ast_json_string_get(ast_json_object_get(message, "type")), ""); msg_application = S_OR( ast_json_string_get(ast_json_object_get(message, "application")), ""); /* If we've been replaced, remove the application from our local websocket_apps container */ if (strcmp(msg_type, "ApplicationReplaced") == 0 && strcmp(msg_application, app_name) == 0) { ao2_find(session->websocket_apps, msg_application, OBJ_UNLINK | OBJ_NODATA); } /* Now, we need to determine our state to see how we will handle the message */ if (ast_json_object_set(message, "application", ast_json_string_create(app_name))) { /* We failed to add an application element to our json message */ ast_log(LOG_WARNING, "Failed to dispatch '%s' message from Stasis app '%s'; could not update message\n", msg_type, msg_application); } else if (!session->ws_session) { /* If the websocket is NULL, the message goes to the queue */ AST_VECTOR_APPEND(&session->message_queue, message); ast_log(LOG_WARNING, "Queued '%s' message for Stasis app '%s'; websocket is not ready\n", msg_type, msg_application); } else { /* We are ready to publish the message */ ast_ari_websocket_session_write(session->ws_session, message); } ao2_unlock(session); }
int ast_ari_bridges_add_channel_parse_body( struct ast_json *body, struct ast_ari_bridges_add_channel_args *args) { struct ast_json *field; /* Parse query parameters out of it */ field = ast_json_object_get(body, "channel"); if (field) { /* If they were silly enough to both pass in a query param and a * JSON body, free up the query value. */ ast_free(args->channel); if (ast_json_typeof(field) == AST_JSON_ARRAY) { /* Multiple param passed as array */ size_t i; args->channel_count = ast_json_array_size(field); args->channel = ast_malloc(sizeof(*args->channel) * args->channel_count); if (!args->channel) { return -1; } for (i = 0; i < args->channel_count; ++i) { args->channel[i] = ast_json_string_get(ast_json_array_get(field, i)); } } else { /* Multiple param passed as single value */ args->channel_count = 1; args->channel = ast_malloc(sizeof(*args->channel) * args->channel_count); if (!args->channel) { return -1; } args->channel[0] = ast_json_string_get(field); } } field = ast_json_object_get(body, "role"); if (field) { args->role = ast_json_string_get(field); } return 0; }
int ast_ari_bridges_start_moh_parse_body( struct ast_json *body, struct ast_ari_bridges_start_moh_args *args) { struct ast_json *field; /* Parse query parameters out of it */ field = ast_json_object_get(body, "mohClass"); if (field) { args->moh_class = ast_json_string_get(field); } return 0; }
int ast_ari_recordings_copy_stored_parse_body( struct ast_json *body, struct ast_ari_recordings_copy_stored_args *args) { struct ast_json *field; /* Parse query parameters out of it */ field = ast_json_object_get(body, "destinationRecordingName"); if (field) { args->destination_recording_name = ast_json_string_get(field); } return 0; }
int ast_ari_playbacks_control_parse_body( struct ast_json *body, struct ast_ari_playbacks_control_args *args) { struct ast_json *field; /* Parse query parameters out of it */ field = ast_json_object_get(body, "operation"); if (field) { args->operation = ast_json_string_get(field); } return 0; }
int ast_ari_asterisk_get_info_parse_body( struct ast_json *body, struct ast_ari_asterisk_get_info_args *args) { struct ast_json *field; /* Parse query parameters out of it */ field = ast_json_object_get(body, "only"); if (field) { /* If they were silly enough to both pass in a query param and a * JSON body, free up the query value. */ ast_free(args->only); if (ast_json_typeof(field) == AST_JSON_ARRAY) { /* Multiple param passed as array */ size_t i; args->only_count = ast_json_array_size(field); args->only = ast_malloc(sizeof(*args->only) * args->only_count); if (!args->only) { return -1; } for (i = 0; i < args->only_count; ++i) { args->only[i] = ast_json_string_get(ast_json_array_get(field, i)); } } else { /* Multiple param passed as single value */ args->only_count = 1; args->only = ast_malloc(sizeof(*args->only) * args->only_count); if (!args->only) { return -1; } args->only[0] = ast_json_string_get(field); } } return 0; }