Changeset 578790e


Ignore:
Timestamp:
2015-04-03T23:20:57Z (9 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Children:
bc73e2ba
Parents:
9ae7332
Message:

Bunch of rpc.c improvements.
It can do requests, responses, but it's all still pretty ugly. Should start
with at least splitting up this pretty big file.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • protocols/rpc/rpc.c

    r9ae7332 r578790e  
    2525        struct groupchat *gc;
    2626};
     27
     28static JSON_Value *jsonrpc_error(int code, const char *msg) {
     29        JSON_Value *error = json_value_init_object();
     30        json_object_set_number(json_object(error), "code", code);
     31        json_object_set_string(json_object(error), "message", msg);
     32        JSON_Value *ret = json_value_init_object();
     33        json_object_set_value(json_object(ret), "error", error);
     34       
     35        return ret;
     36}
    2737
    2838static JSON_Value *rpc_out_new(const char *method, JSON_Array **params_) {
     
    8999        struct rpc_connection *rd = ic->proto_data = g_new0(struct rpc_connection, 1);
    90100        struct rpc_plugin *pd = acc->prpl->data;
     101        imcb_log(ic, "Connecting to RPC server");
    91102        rd->fd = socket(pd->addr->sa_family, SOCK_STREAM, 0);
    92103        sock_make_nonblocking(rd->fd);
     
    229240}
    230241
    231 static struct groupchat *rpc_groupchat_new(struct im_connection *ic, const char *handle) {
     242static struct rpc_groupchat *rpc_groupchat_new(struct im_connection *ic, const char *handle) {
     243        struct rpc_connection *rd = ic->proto_data;
    232244        struct groupchat *gc = imcb_chat_new(ic, handle);
    233245        struct rpc_groupchat *rc = gc->data = g_new0(struct rpc_groupchat, 1);
    234         rc->id = next_rpc_id;
     246        rc->id = next_rpc_id++;
    235247        rc->gc = gc;
    236         return gc;  // TODO: RETVAL HERE AND BELOW
    237 }
     248        g_hash_table_insert(rd->groupchats, &rc->id, rc);
     249        return rc;  // TODO: RETVAL HERE AND BELOW
     250}
     251
     252static struct rpc_groupchat *rpc_groupchat_by_id(struct im_connection *ic, int id) {
     253        struct rpc_connection *rd = ic->proto_data;
     254        struct rpc_groupchat *rc = g_hash_table_lookup(rd->groupchats, &id);
     255
     256        return rc;
     257}
     258
     259/* Boilerplate for all incoming RPCs (where groupchat is identified using
     260 * numeric ID). */
     261#define SET_GROUPCHAT(rc) \
     262        do { \
     263                rc = rpc_groupchat_by_id(ic, json_array_get_number(params, 0)); \
     264                if (rc == NULL) \
     265                        return jsonrpc_error(ENOENT, "No groupchat with that id."); \
     266        } while (0)
    238267
    239268static struct groupchat *rpc_chat_with(struct im_connection *ic, char *who) {
    240269        RPC_OUT_INIT("chat_with");
    241         struct groupchat *gc = rpc_groupchat_new(ic, who);
    242         struct rpc_groupchat *rc = gc->data;
     270        struct rpc_groupchat *rc = rpc_groupchat_new(ic, who);
    243271        json_array_append_number(params, rc->id);
    244272        json_array_append_string(params, who);
    245273        rpc_send(ic, rpc);
    246274
    247         return gc;
     275        return rc->gc;
    248276}
    249277
     
    251279                                       const char *password, set_t **sets) {
    252280        RPC_OUT_INIT("chat_join");
    253         struct groupchat *gc = rpc_groupchat_new(ic, room);
    254         struct rpc_groupchat *rc = gc->data;
     281        struct rpc_groupchat *rc = rpc_groupchat_new(ic, room);
    255282        json_array_append_number(params, rc->id);
    256283        json_array_append_string(params, room);
     
    260287        rpc_send(ic, rpc);
    261288
    262         return gc;
     289        return rc->gc;
    263290}
    264291
     
    271298}
    272299
    273 static gboolean rpc_cmd_in(struct im_connection *ic, const char *cmd, JSON_Array *params);
     300static JSON_Value *rpc_cmd_in(struct im_connection *ic, const char *cmd, JSON_Array *params);
    274301
    275302static gboolean rpc_in(struct im_connection *ic, JSON_Object *rpc) {
    276         JSON_Object *res = json_object_get_object(rpc, "result");
    277303        const char *cmd = json_object_get_string(rpc, "method");
    278304        JSON_Value *id = json_object_get_value(rpc, "id");
    279305        JSON_Array *params = json_object_get_array(rpc, "params");
    280306
    281         if ((!cmd && !res) || !id || (cmd && !params)) {
     307        /* Removed checks for result/error/etc. as it's all too free-form and
     308         * at least for now this code is not going to care about retvals as
     309         * they come in late anyway. */
     310        if (!id) {
    282311                imcb_log(ic, "Received invalid JSON-RPC object.");
    283312                imc_logout(ic, TRUE);
     
    285314        }
    286315
    287         if (res) {
    288                 // handle response. I think I mostly won't.
    289                 return TRUE;
    290         } else {
    291                 gboolean st = rpc_cmd_in(ic, cmd, params);
    292                 JSON_Value *resp = json_value_init_object();
     316        if (cmd) {
     317                JSON_Value *resp = rpc_cmd_in(ic, cmd, params);
     318                if (!resp) {
     319                        resp = json_value_init_object();
     320                        json_object_set_boolean(json_object(resp), "result", TRUE);
     321                }
    293322                json_object_set_value(json_object(resp), "id", json_value_deep_copy(id));
    294                 if (st)
    295                         json_object_set_value(json_object(resp), "result", json_value_init_object());
    296                 else
    297                         json_object_set_value(json_object(resp), "error", json_value_init_object());
    298323                return rpc_send(ic, resp);
    299324        }
     325
     326        return TRUE;
    300327}
    301328
     
    313340
    314341        if (st == 0 || (st == -1 && !(sockerr_again() || errno == EAGAIN))) {
    315                 imcb_log(ic, "Read error");
     342                imcb_log(ic, "Lost RPC connection");
    316343                imc_logout(ic, TRUE);
    317344                return FALSE;
     
    345372}
    346373
    347 static void rpc_imcb_log(struct im_connection *ic, void *func_, JSON_Array *params) {
    348         void (*func)(struct im_connection*, char*, ...) = func_;
     374static JSON_Value *rpc_imcb_log(struct im_connection *ic, void *func_, JSON_Array *params) {
     375        void (*func)(struct im_connection*, const char*, ...) = func_;
    349376        func(ic, "%s", json_array_get_string(params, 0));
    350 }
    351 
    352 static void rpc_imcb_connected(struct im_connection *ic, void *func_, JSON_Array *params) {
     377        return NULL;
     378}
     379
     380static JSON_Value *rpc_imcb_connected(struct im_connection *ic, void *func_, JSON_Array *params) {
    353381        void (*func)(struct im_connection*) = func_;
    354382        func(ic);
    355 }
    356 
    357 static void rpc_imc_logout(struct im_connection *ic, void *func_, JSON_Array *params) {
     383        return NULL;
     384}
     385
     386static JSON_Value *rpc_imc_logout(struct im_connection *ic, void *func_, JSON_Array *params) {
    358387        void (*func)(struct im_connection*, gboolean) = func_;
    359388        func(ic, json_array_get_boolean(params, 0));
    360 }
    361 
    362 static void rpc_imcb_add_buddy(struct im_connection *ic, void *func_, JSON_Array *params) {
     389        return NULL;
     390}
     391
     392static JSON_Value *rpc_imcb_add_buddy(struct im_connection *ic, void *func_, JSON_Array *params) {
    363393        void (*func)(struct im_connection*, const char*, const char*) = func_;
    364394        func(ic, json_array_get_string(params, 0), json_array_get_string(params, 1));
    365 }
    366 
    367 static void rpc_imcb_buddy_status(struct im_connection *ic, void *func_, JSON_Array *params) {
     395        return NULL;
     396}
     397
     398static JSON_Value *rpc_imcb_buddy_status(struct im_connection *ic, void *func_, JSON_Array *params) {
    368399        void (*func)(struct im_connection*, const char*, int, const char*, const char*) = func_;
    369400        func(ic, json_array_get_string(params, 0), json_array_get_number(params, 1),
    370401                 json_array_get_string(params, 2), json_array_get_string(params, 3));
    371 }
    372 
    373 static void rpc_imcb_buddy_times(struct im_connection *ic, void *func_, JSON_Array *params) {
     402        return NULL;
     403}
     404
     405static JSON_Value *rpc_imcb_buddy_times(struct im_connection *ic, void *func_, JSON_Array *params) {
    374406        void (*func)(struct im_connection*, const char*, int, int) = func_;
    375407        func(ic, json_array_get_string(params, 0), json_array_get_number(params, 1),
    376408                 json_array_get_number(params, 2));
    377 }
    378 
    379 static void rpc_imcb_buddy_msg(struct im_connection *ic, void *func_, JSON_Array *params) {
     409        return NULL;
     410}
     411
     412static JSON_Value *rpc_imcb_buddy_msg(struct im_connection *ic, void *func_, JSON_Array *params) {
    380413        void (*func)(struct im_connection*, const char*, const char*, int, int) = func_;
    381414        func(ic, json_array_get_string(params, 0), json_array_get_string(params, 1),
    382415                 json_array_get_number(params, 2), json_array_get_number(params, 3));
    383 }
    384 
    385 static void rpc_imcb_buddy_typing(struct im_connection *ic, void *func_, JSON_Array *params) {
    386         void (*func)(struct im_connection*, char*, int) = func_;
     416        return NULL;
     417}
     418
     419static JSON_Value *rpc_imcb_buddy_typing(struct im_connection *ic, void *func_, JSON_Array *params) {
     420        void (*func)(struct im_connection*, const char*, int) = func_;
    387421        func(ic, (char*) json_array_get_string(params, 0), json_array_get_number(params, 1));
     422        return NULL;
     423}
     424
     425static JSON_Value *rpc_imcb_chat_new(struct im_connection *ic, void *func_, JSON_Array *params) {
     426        struct rpc_groupchat *rc = rpc_groupchat_new(ic, json_array_get_string(params, 0));
     427        JSON_Value *resp = json_value_init_object();
     428        json_object_set_number(json_object(resp), "result", rc->id);
     429        return resp;
     430}
     431
     432static JSON_Value *rpc_imcb_chat_name_hint(struct im_connection *ic, void *func_, JSON_Array *params) {
     433        void (*func)(struct groupchat*, const char*) = func_;
     434        struct rpc_groupchat *rc;
     435        SET_GROUPCHAT(rc);
     436        func(rc->gc, json_array_get_string(params, 1));
     437        return NULL;
     438}
     439
     440static JSON_Value *rpc_imcb_chat_msg(struct im_connection *ic, void *func_, JSON_Array *params) {
     441        void (*func)(struct groupchat*, const char*, const char*, guint32, time_t) = func_;
     442        struct rpc_groupchat *rc;
     443        SET_GROUPCHAT(rc);
     444        func(rc->gc, json_array_get_string(params, 1), json_array_get_string(params, 2),
     445             json_array_get_number(params, 3), json_array_get_number(params, 4));
     446        return NULL;
     447}
     448
     449static JSON_Value *rpc_imcb_chat_log(struct im_connection *ic, void *func_, JSON_Array *params) {
     450        void (*func)(struct groupchat*, const char*, ...) = func_;
     451        struct rpc_groupchat *rc;
     452        SET_GROUPCHAT(rc);
     453        func(rc->gc, "%s", json_array_get_string(params, 1));
     454        return NULL;
     455}
     456
     457static JSON_Value *rpc_imcb_chat_topic(struct im_connection *ic, void *func_, JSON_Array *params) {
     458        void (*func)(struct groupchat*, const char*, const char*, time_t) = func_;
     459        struct rpc_groupchat *rc;
     460        SET_GROUPCHAT(rc);
     461        func(rc->gc, json_array_get_string(params, 1), json_array_get_string(params, 2),
     462             json_array_get_number(params, 3));
     463        return NULL;
     464}
     465
     466static JSON_Value *rpc_imcb_chat_remove_buddy(struct im_connection *ic, void *func_, JSON_Array *params) {
     467        void (*func)(struct groupchat*, const char*, const char*) = func_;
     468        struct rpc_groupchat *rc;
     469        SET_GROUPCHAT(rc);
     470        func(rc->gc, json_array_get_string(params, 1), json_array_get_string(params, 2));
     471        return NULL;
     472}
     473
     474static JSON_Value *rpc_imcb_chat_invite(struct im_connection *ic, void *func_, JSON_Array *params) {
     475        void (*func)(struct groupchat*, const char*, const char*, const char*) = func_;
     476        struct rpc_groupchat *rc;
     477        SET_GROUPCHAT(rc);
     478        func(rc->gc, json_array_get_string(params, 1), json_array_get_string(params, 2),
     479             json_array_get_string(params, 3));
     480        return NULL;
    388481}
    389482
     
    391484        char *name;
    392485        void *func;
    393         void (* wfunc) (struct im_connection *ic, void *cmd, JSON_Array *params);
     486        JSON_Value* (* wfunc) (struct im_connection *ic, void *cmd, JSON_Array *params);
    394487        char args[8];
    395488};
    396489
    397490static const struct rpc_in_method methods[] = {
     491        /* All these RPCs are equivalent of BitlBee C functions but with the
     492         * struct im_connection* removed. */
    398493        { "imcb_log", imcb_log, rpc_imcb_log, "s" },
    399494        { "imcb_error", imcb_error, rpc_imcb_log, "s" },
     
    409504        { "imcb_buddy_msg", imcb_buddy_msg, rpc_imcb_buddy_msg, "ssnn" },
    410505        { "imcb_buddy_typing", imcb_buddy_typing, rpc_imcb_buddy_typing, "sn" },
     506        { "imcb_chat_new", NULL, rpc_imcb_chat_new, "s" },
     507       
     508        /* RPCs below are equivalent, but with the struct groupchat* replaced
     509         * with the numeric id of the chat. */
     510        { "imcb_chat_name_hint", imcb_chat_name_hint, rpc_imcb_chat_name_hint, "ns" },
     511        { "imcb_chat_msg", imcb_chat_msg, rpc_imcb_chat_msg, "nssnn" },
     512        { "imcb_chat_log", imcb_chat_log, rpc_imcb_chat_log, "ns" },
     513        { "imcb_chat_topic", imcb_chat_topic, rpc_imcb_chat_topic, "nssn" },
     514        { "imcb_chat_add_buddy", imcb_chat_add_buddy, rpc_imcb_chat_name_hint, "ns" },
     515        { "imcb_chat_remove_buddy", imcb_chat_remove_buddy, rpc_imcb_chat_remove_buddy, "nss" },
     516        { "imcb_chat_invite", imcb_chat_invite, rpc_imcb_chat_invite, "nsss" },
     517
    411518        { NULL },
    412519};
    413520
    414 static gboolean rpc_cmd_in(struct im_connection *ic, const char *cmd, JSON_Array *params) {
     521static JSON_Value *rpc_cmd_in(struct im_connection *ic, const char *cmd, JSON_Array *params) {
    415522        int i;
    416523
     
    419526                        if (json_array_get_count(params) != strlen(methods[i].args)) {
    420527                                imcb_error(ic, "Invalid argument count to method %s: %d, wanted %zd", cmd, (int) json_array_get_count(params), strlen(methods[i].args));
    421                                 return FALSE;
     528                                return jsonrpc_error(E2BIG, "Invalid number of arguments");
    422529                        }
    423530                        int j;
     
    445552                                        // This error sucks, but just get your types right!
    446553                                        imcb_error(ic, "Invalid argument type, %s parameter %d: %d not %c", cmd, j, type, methods[i].args[j]);
    447                                         return FALSE;
     554                                        return jsonrpc_error(EINVAL, "Invalid argument type");
    448555                                }
    449556                        }
    450                         methods[i].wfunc(ic, methods[i].func, params);
    451                         return TRUE;
     557                        return methods[i].wfunc(ic, methods[i].func, params);
    452558                }
    453559        }
    454         return FALSE;
     560        return jsonrpc_error(ENOSYS, "Function not implemented");
    455561}
    456562
     
    558664        // TODO: Property for a few standard nickcmp implementations.
    559665       
     666        struct rpc_plugin *proto_data = g_new0(struct rpc_plugin, 1);
     667        proto_data->addr = g_memdup(address, addrlen);
     668        proto_data->addrlen = addrlen;
     669        ret->name = g_strdup(json_object_get_string(isup, "name"));
     670        ret->data = proto_data;
     671
    560672        JSON_Array *settings = json_object_get_array(isup, "settings");
    561673        for (i = 0; i < json_array_get_count(settings); i++) {
     
    563675                // set..name, set..type, set..default, set..flags ?
    564676        }
    565 
    566         ret->name = g_strdup(json_object_get_string(isup, "name"));
    567 
    568         struct rpc_plugin *proto_data = g_new0(struct rpc_plugin, 1);
    569         proto_data->addr = g_memdup(address, addrlen);
    570         proto_data->addrlen = addrlen;
    571         ret->data = proto_data;
    572677
    573678        register_protocol(ret);
Note: See TracChangeset for help on using the changeset viewer.