Add filter by service / name to restful rhizome list

This commit is contained in:
Jeremy Lakeman 2016-10-12 11:06:50 +10:30
parent 86d4d87ff2
commit 8e9877b3ce
5 changed files with 115 additions and 111 deletions

@ -13,8 +13,9 @@ import java.net.HttpURLConnection;
*/
public class MeshMBCommon {
public static int sendMessage(ServalDHttpConnectionFactory connector, SigningKey id, String text) throws IOException, ServalDInterfaceException
{
public static final String SERVICE = "MeshMB1";
public static int sendMessage(ServalDHttpConnectionFactory connector, SigningKey id, String text) throws IOException, ServalDInterfaceException {
HttpURLConnection conn = connector.newServalDHttpConnection("/restful/meshmb/" + id.toHex() + "/sendmessage");
PostHelper helper = new PostHelper(conn);
helper.connect();

@ -1,5 +1,6 @@
package org.servalproject.servaldna.meshmb;
import org.servalproject.json.JSONInputException;
import org.servalproject.json.JSONTableScanner;
import org.servalproject.json.JSONTokeniser;
import org.servalproject.servaldna.AbstractJsonList;

@ -34,6 +34,7 @@ import java.net.URL;
public class MeshMSCommon
{
public static final String SERVICE = "MeshMS2";
protected static JSONTokeniser receiveRestfulResponse(HttpURLConnection conn, int expected_response_code) throws IOException, ServalDInterfaceException, MeshMSException
{
int[] expected_response_codes = { expected_response_code };

@ -20,9 +20,9 @@
package org.servalproject.servaldna.rhizome;
import org.servalproject.json.JSONInputException;
import org.servalproject.json.JSONTableScanner;
import org.servalproject.json.JSONTokeniser;
import org.servalproject.servaldna.AbstractJsonList;
import org.servalproject.servaldna.BundleId;
import org.servalproject.servaldna.FileHash;
import org.servalproject.servaldna.ServalDHttpConnectionFactory;
@ -30,122 +30,95 @@ import org.servalproject.servaldna.ServalDInterfaceException;
import org.servalproject.servaldna.SubscriberId;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.util.Map;
public class RhizomeBundleList {
public class RhizomeBundleList extends AbstractJsonList<RhizomeListBundle, IOException> {
private ServalDHttpConnectionFactory httpConnector;
private HttpURLConnection httpConnection;
private JSONTokeniser json;
private JSONTableScanner table;
private String sinceToken;
int rowCount;
private String service;
private String name;
public RhizomeBundleList(ServalDHttpConnectionFactory connector)
{
this(connector, null);
}
public void setServiceFilter(String service){
this.service = service;
}
public void setNameFilter(String name){
this.name = name;
}
public RhizomeBundleList(ServalDHttpConnectionFactory connector, String since_token)
{
this.httpConnector = connector;
this.table = new JSONTableScanner()
.addColumn("_id", Integer.class)
.addColumn(".token", String.class, JSONTokeniser.Narrow.ALLOW_NULL)
.addColumn("service", String.class)
.addColumn("id", BundleId.class)
.addColumn("version", Long.class)
.addColumn("date", Long.class)
.addColumn(".inserttime", Long.class)
.addColumn(".author", SubscriberId.class, JSONTokeniser.Narrow.ALLOW_NULL)
.addColumn(".fromhere", Integer.class)
.addColumn("filesize", Long.class)
.addColumn("filehash", FileHash.class, JSONTokeniser.Narrow.ALLOW_NULL)
.addColumn("sender", SubscriberId.class, JSONTokeniser.Narrow.ALLOW_NULL)
.addColumn("recipient", SubscriberId.class, JSONTokeniser.Narrow.ALLOW_NULL)
.addColumn("name", String.class, JSONTokeniser.Narrow.ALLOW_NULL);
super(connector, new JSONTableScanner()
.addColumn("_id", Integer.class)
.addColumn(".token", String.class, JSONTokeniser.Narrow.ALLOW_NULL)
.addColumn("service", String.class)
.addColumn("id", BundleId.class)
.addColumn("version", Long.class)
.addColumn("date", Long.class)
.addColumn(".inserttime", Long.class)
.addColumn(".author", SubscriberId.class, JSONTokeniser.Narrow.ALLOW_NULL)
.addColumn(".fromhere", Integer.class)
.addColumn("filesize", Long.class)
.addColumn("filehash", FileHash.class, JSONTokeniser.Narrow.ALLOW_NULL)
.addColumn("sender", SubscriberId.class, JSONTokeniser.Narrow.ALLOW_NULL)
.addColumn("recipient", SubscriberId.class, JSONTokeniser.Narrow.ALLOW_NULL)
.addColumn("name", String.class, JSONTokeniser.Narrow.ALLOW_NULL));
this.sinceToken = since_token;
}
public boolean isConnected()
{
return this.json != null;
@Override
protected String getUrl() {
String url;
if (this.sinceToken == null)
url = "/restful/rhizome/bundlelist.json";
else if(this.sinceToken.equals(""))
url = "/restful/rhizome/newsince/bundlelist.json";
else
url = "/restful/rhizome/newsince/" + this.sinceToken + "/bundlelist.json";
String parms="";
if (service != null)
parms += "service="+service;
if (name!=null) {
if (!"".equals(parms))
parms+="&";
parms += "name=" + name;
}
if (!"".equals(parms))
url+="?"+parms;
return url;
}
public void connect() throws IOException, ServalDInterfaceException
{
try {
rowCount = 0;
if (this.sinceToken == null)
httpConnection = httpConnector.newServalDHttpConnection("/restful/rhizome/bundlelist.json");
else if(this.sinceToken.equals(""))
httpConnection = httpConnector.newServalDHttpConnection("/restful/rhizome/newsince/bundlelist.json");
else
httpConnection = httpConnector.newServalDHttpConnection("/restful/rhizome/newsince/" + this.sinceToken + "/bundlelist.json");
httpConnection.connect();
json = RhizomeCommon.receiveRestfulResponse(httpConnection, HttpURLConnection.HTTP_OK);
json.consume(JSONTokeniser.Token.START_OBJECT);
json.consume("header");
json.consume(JSONTokeniser.Token.COLON);
table.consumeHeaderArray(json);
json.consume(JSONTokeniser.Token.COMMA);
json.consume("rows");
json.consume(JSONTokeniser.Token.COLON);
json.consume(JSONTokeniser.Token.START_ARRAY);
}
catch (JSONInputException e) {
throw new ServalDInterfaceException(e);
}
@Override
protected RhizomeListBundle factory(Map<String, Object> row, long rowCount) throws ServalDInterfaceException {
return new RhizomeListBundle(
new RhizomeManifest((BundleId)row.get("id"),
(Long)row.get("version"),
(Long)row.get("filesize"),
(FileHash)row.get("filehash"),
(SubscriberId)row.get("sender"),
(SubscriberId)row.get("recipient"),
null, // BK
null, // crypt
null, // tail
(Long)row.get("date"),
(String)row.get("service"),
(String)row.get("name")),
(int)rowCount,
(Integer)row.get("_id"),
(String)row.get(".token"),
(Long)row.get(".inserttime"),
(SubscriberId)row.get(".author"),
(Integer)row.get(".fromhere")
);
}
@Deprecated
public RhizomeListBundle nextBundle() throws ServalDInterfaceException, IOException
{
try {
Object tok = json.nextToken();
if (tok == JSONTokeniser.Token.END_ARRAY) {
json.consume(JSONTokeniser.Token.END_OBJECT);
json.consume(JSONTokeniser.Token.EOF);
return null;
}
if (rowCount != 0)
JSONTokeniser.match(tok, JSONTokeniser.Token.COMMA);
else
json.pushToken(tok);
Map<String,Object> row = table.consumeRowArray(json);
return new RhizomeListBundle(
new RhizomeManifest((BundleId)row.get("id"),
(Long)row.get("version"),
(Long)row.get("filesize"),
(FileHash)row.get("filehash"),
(SubscriberId)row.get("sender"),
(SubscriberId)row.get("recipient"),
null, // BK
null, // crypt
null, // tail
(Long)row.get("date"),
(String)row.get("service"),
(String)row.get("name")),
rowCount++,
(Integer)row.get("_id"),
(String)row.get(".token"),
(Long)row.get(".inserttime"),
(SubscriberId)row.get(".author"),
(Integer)row.get(".fromhere")
);
}
catch (JSONInputException e) {
throw new ServalDInterfaceException(e);
}
return next();
}
public void close() throws IOException
{
httpConnection = null;
if (json != null) {
json.close();
json = null;
}
}
}

@ -47,6 +47,16 @@ static void finalise_union_rhizome_insert(httpd_request *r)
rhizome_fail_write(&r->u.insert.write);
}
static void finalise_union_rhizome_list(httpd_request *r)
{
if (r->u.rhlist.cursor.service)
free((void*)r->u.rhlist.cursor.service);
r->u.rhlist.cursor.service=NULL;
if (r->u.rhlist.cursor.name)
free((void*)r->u.rhlist.cursor.name);
r->u.rhlist.cursor.name=NULL;
}
#define LIST_TOKEN_STRLEN (BASE64_ENCODED_LEN(sizeof(serval_uuid_t) + 8))
#define alloca_list_token(rowid) list_token_to_str(alloca(LIST_TOKEN_STRLEN + 1), (rowid))
@ -176,6 +186,33 @@ static int http_request_rhizome_response(struct httpd_request *r, uint16_t http_
static HTTP_CONTENT_GENERATOR restful_rhizome_bundlelist_json_content;
static int restful_open_cursor(httpd_request *r)
{
assert(r->finalise_union == NULL);
r->finalise_union = finalise_union_rhizome_list;
r->u.rhlist.phase = LIST_HEADER;
r->u.rhlist.rowcount = 0;
const char *service = http_request_get_query_param(&r->http, "service");
if (service && *service){
r->u.rhlist.cursor.service = str_edup(service);
// TODO fail?
}
const char *name = http_request_get_query_param(&r->http, "name");
if (name && *name){
r->u.rhlist.cursor.name = str_edup(name);
// TODO fail?
}
int ret = rhizome_list_open(&r->u.rhlist.cursor);
if (ret == -1)
return http_request_rhizome_response(r, 500, "Failed to open list");
http_request_response_generated(&r->http, 200, CONTENT_TYPE_JSON, restful_rhizome_bundlelist_json_content);
return 1;
}
static int restful_rhizome_bundlelist_json(httpd_request *r, const char *remainder)
{
r->http.response.header.content_type = CONTENT_TYPE_JSON;
@ -189,11 +226,8 @@ static int restful_rhizome_bundlelist_json(httpd_request *r, const char *remaind
return 404;
if (r->http.verb != HTTP_VERB_GET)
return 405;
r->u.rhlist.phase = LIST_HEADER;
r->u.rhlist.rowcount = 0;
bzero(&r->u.rhlist.cursor, sizeof r->u.rhlist.cursor);
http_request_response_generated(&r->http, 200, CONTENT_TYPE_JSON, restful_rhizome_bundlelist_json_content);
return 1;
return restful_open_cursor(r);
}
static HTTP_CONTENT_GENERATOR_STRBUF_CHUNKER restful_rhizome_bundlelist_json_content_chunk;
@ -201,10 +235,7 @@ static HTTP_CONTENT_GENERATOR_STRBUF_CHUNKER restful_rhizome_bundlelist_json_con
static int restful_rhizome_bundlelist_json_content(struct http_request *hr, unsigned char *buf, size_t bufsz, struct http_content_generator_result *result)
{
httpd_request *r = (httpd_request *) hr;
int ret = rhizome_list_open(&r->u.rhlist.cursor);
if (ret == -1)
return -1;
ret = generate_http_content_from_strbuf_chunks(hr, (char *)buf, bufsz, result, restful_rhizome_bundlelist_json_content_chunk);
int ret = generate_http_content_from_strbuf_chunks(hr, (char *)buf, bufsz, result, restful_rhizome_bundlelist_json_content_chunk);
rhizome_list_release(&r->u.rhlist.cursor);
return ret;
}
@ -223,15 +254,12 @@ static int restful_rhizome_newsince(httpd_request *r, const char *remainder)
return 404;
if (r->http.verb != HTTP_VERB_GET)
return 405;
r->u.rhlist.phase = LIST_HEADER;
r->u.rhlist.rowcount = 0;
bzero(&r->u.rhlist.cursor, sizeof r->u.rhlist.cursor);
r->u.rhlist.cursor.rowid_since = rowid;
r->u.rhlist.cursor.oldest_first = 1;
r->u.rhlist.end_time = gettime_ms() + config.api.restful.newsince_timeout * 1000;
r->trigger_rhizome_bundle_added = on_rhizome_bundle_added;
http_request_response_generated(&r->http, 200, CONTENT_TYPE_JSON, restful_rhizome_bundlelist_json_content);
return 1;
return restful_open_cursor(r);
}
static void on_rhizome_bundle_added(httpd_request *r, rhizome_manifest *UNUSED(m))