/** Close connection to the server. * * @param cb 3E calendar backend. */ void e_cal_backend_3e_close_connection(ECalBackend3e *cb) { g_return_if_fail(cb != NULL); if (cb->priv->is_open) { xr_client_close(cb->priv->conn); cb->priv->is_open = FALSE; g_static_rec_mutex_unlock(&cb->priv->conn_mutex); } }
void xr_client_free(xr_client_conn* conn) { xr_trace(XR_DEBUG_CLIENT_TRACE, "(conn=%p)", conn); if (conn == NULL) return; xr_client_close(conn); g_free(conn->host); g_free(conn->resource); g_free(conn->session_id); g_hash_table_destroy(conn->headers); g_free(conn); }
/** Open connection to the 3E server and authenticate user. * * This function will do nothing and return TRUE if connection is already * opened. * * @param cb 3E calendar backend. * @param err Error pointer. * * @return TRUE if connection was already open, FALSE on error. */ gboolean e_cal_backend_3e_open_connection(ECalBackend3e *cb, GError * *err) { GError *local_err = NULL; g_return_val_if_fail(cb != NULL, FALSE); g_return_val_if_fail(err == NULL || *err == NULL, FALSE); cb->priv->last_conn_failed = FALSE; /* if user tried to open connection in offline mode, close current connection if any and return error. this shouldn't happen, but let's check it anyway */ if (!e_cal_backend_3e_calendar_is_online(cb)) { g_set_error(err, 0, -1, "Can't open 3e server connection in offline mode."); e_cal_backend_3e_close_connection(cb); return FALSE; } g_static_rec_mutex_lock(&cb->priv->conn_mutex); /* resolve server URI from DNS TXT if necessary */ if (cb->priv->server_uri == NULL) { char *server_hostname = get_eee_server_hostname(cb->priv->username); if (server_hostname == NULL) { g_set_error(err, 0, -1, "Can't resolve server URI for username '%s'", cb->priv->username); goto err; } cb->priv->server_uri = g_strdup_printf("https://%s/RPC2", server_hostname); g_free(server_hostname); } /* check that we have all info that is necessary to create conn */ if (cb->priv->username == NULL || cb->priv->password == NULL || cb->priv->server_uri == NULL) { g_set_error(err, 0, -1, "Connection was not setup correctly, can't open."); goto err; } /* create conn object */ if (cb->priv->conn == NULL) { cb->priv->conn = xr_client_new(err); if (cb->priv->conn == NULL) { goto err; } cb->priv->is_open = FALSE; } if (cb->priv->is_open) { /* was already locked in this thread */ g_static_rec_mutex_unlock(&cb->priv->conn_mutex); return TRUE; } if (!xr_client_open(cb->priv->conn, cb->priv->server_uri, err)) { goto err; } ESClient_authenticate(cb->priv->conn, cb->priv->username, cb->priv->password, &local_err); if (local_err) { g_propagate_error(err, local_err); xr_client_close(cb->priv->conn); goto err; } cb->priv->is_open = TRUE; return TRUE; err: cb->priv->last_conn_failed = TRUE; g_static_rec_mutex_unlock(&cb->priv->conn_mutex); return FALSE; }
gboolean xr_client_call(xr_client_conn* conn, xr_call* call, GError** err) { char* buffer; int length; gboolean rs; gboolean write_success; GString* response; xr_trace(XR_DEBUG_CLIENT_TRACE, "(conn=%p, call=%p)", conn, call); g_return_val_if_fail(conn != NULL, FALSE); g_return_val_if_fail(call != NULL, FALSE); g_return_val_if_fail(err == NULL || *err == NULL, FALSE); if (!conn->is_open) { g_set_error(err, XR_CLIENT_ERROR, XR_CLIENT_ERROR_CLOSED, "Can't perform RPC on closed connection."); return FALSE; } /* serialize nad send XML-RPC request */ xr_call_set_transport(call, conn->transport); xr_call_serialize_request(call, &buffer, &length); xr_http_setup_request(conn->http, "POST", conn->resource, conn->host); g_hash_table_foreach(conn->headers, (GHFunc)_add_http_header, conn->http); if (conn->transport == XR_CALL_XML_RPC) xr_http_set_header(conn->http, "Content-Type", "text/xml"); #ifdef XR_JSON_ENABLED else if (conn->transport == XR_CALL_JSON_RPC) xr_http_set_header(conn->http, "Content-Type", "text/json"); #endif xr_http_set_message_length(conn->http, length); write_success = xr_http_write_all(conn->http, buffer, length, err); xr_call_free_buffer(call, buffer); if (!write_success) { xr_client_close(conn); return FALSE; } /* receive HTTP response header */ if (!xr_http_read_header(conn->http, err)) return FALSE; /* check if some dumb bunny sent us wrong message type */ if (xr_http_get_message_type(conn->http) != XR_HTTP_RESPONSE) return FALSE; response = xr_http_read_all(conn->http, err); if (response == NULL) { xr_client_close(conn); return FALSE; } rs = xr_call_unserialize_response(call, response->str, response->len); g_string_free(response, TRUE); if (!rs) { g_set_error(err, 0, xr_call_get_error_code(call), "%s", xr_call_get_error_message(call)); if (xr_debug_enabled & XR_DEBUG_CALL) xr_call_dump(call, 0); return FALSE; } if (xr_debug_enabled & XR_DEBUG_CALL) xr_call_dump(call, 0); return TRUE; }