source: protocols/rpc/rpc.c @ 3434a8c

Last change on this file since 3434a8c was 4f6dfbb, checked in by Wilmer van der Gaast <wilmer@…>, at 2015-02-25T00:35:55Z

Did a fair amount of work on it by now, might as well do a checkin. No
Makefile or whatever yet, haven't even tried compiling it, I don't expect
that it would go well at all at this stage.

  • Property mode set to 100644
File size: 5.0 KB
Line 
1
2static int next_rpc_id = 1;
3
4struct rpc_protocol {
5        struct sockaddr *addr;
6        socklen_t addrlen;
7}
8
9struct rpc_connection {
10        int fd;
11        char *buf;
12}
13
14struct rpc_groupchat {
15        struct groupchat *bee_gc;
16        char *rpc_handle;
17}
18
19static JSON_Value *rpc_out_new(const char *method, JSON_Array **params_) {
20        JSON_Value *rpc = json_value_init_object();
21        json_set_string(rpc, "method", "chat_msg");
22        json_set_number(rpc, "id", next_rpc_id++);
23
24        JSON_Array *params = json_value_init_array();
25        json_object_set_value(rpc, "params", params);
26
27        if (params_)
28                *params_ = json_array(params);
29}
30
31#define RPC_OUT_INIT(method) \
32        JSON_Array *params; \
33        JSON_Value *rpc = rpc_out_new(method, &params);
34
35/** Sends an RPC object. Takes ownership (i.e. frees it when done). */
36static void rpc_send(struct im_connection *ic, JSON_Value *rpc) {
37        char *buf = json_serialize_to_string(rpc);
38
39        g_free(buf);
40        json_value_free(rpc);
41}
42
43static JSON_Object *rpc_ser_account(const account_t *acc) {
44        JSON_Value *v = json_value_init_object();
45        JSON_Object *o = json_object(v);
46        json_object_set_string(o, "user", acc->user);
47        json_object_set_string(o, "pass", acc->user);
48        json_object_set_string(o, "server", acc->server);
49        return v;
50}
51
52static void rpc_init(account_t *acc) {
53        // Add settings. Probably should not RPC at all.
54}
55
56static void rpc_login(account_t *acc) {
57        struct im_connection *ic = imcb_new(acc);
58        RPC_OUT_INIT("login");
59        json_array_append_value(params, rpc_ser_account(acc));
60        rpc_send(gc->ic, rpc);
61        // Create im
62}
63
64static void rpc_chat_msg(struct groupchat *gc, char *msg, int flags) {
65        RPC_OUT_INIT("chat_msg");       
66        struct rpc_groupchat *data = gc->proto_data;
67        json_array_append_string(params, data->rpc_handle);
68        json_array_append_string(params, msg);
69        json_array_append_number(params, flags);
70        rpc_send(gc->ic, rpc);
71}
72
73static void rpc_in(JSON_Object *rpc) {
74        JSON_Object *res = json_object_get_object(rpc, "result");
75        const char *cmd = json_object_get_string(rpc, "method");
76        JSON_Value *Value *id = json_object_get_value(rpc, "id");
77        JSON_Array *params *params = json_object_get_array(rpc, "params");
78
79        if ((!cmd && !res) || !id || (cmd && !params)) {
80                imcb_logout(ic, "Received invalid JSON-RPC object.");
81                return;
82        }
83
84        if (res) {
85                // handle response. I think I mostly won't.
86        } else {
87                rpc_cmd_in(cmd, params);
88        }
89}
90
91static void rpc_imcb_buddy_typing(struct im_connection *ic, const char *cmd, JSON_Array *params) {
92        const char *handle = json_array_get_string(params, 0);
93        int flags = json_array_get_number(params, 1);
94        imcb_buddy_typing(ic, handle, flags);
95}
96
97struct rpc_in_method {
98        char *name;
99        void (* func) (struct im_connection *ic, const char *cmd, JSON_Array *params);
100        char *args;
101}
102
103static void rpc_cmd_in(const char *cmd, JSON_Array *params) {
104
105}
106
107#define RPC_ADD_FUNC(func) \
108        if (g_hash_table_contains(methods, #func)) \
109                ret->func = rpc_ # func
110
111void rpc_initmodule_sock(struct sockaddr *address, socklen addrlen) {
112        int st, fd, i;
113
114        fd = socket(address->ss_family, SOCK_STREAM);
115        if (fd == -1 || connect(fd, address, addrlen) == -1)
116                return;
117
118        RPC_OUT_INIT("init");
119        JSON_Value *d = json_value_init_object();
120        json_object_set_string(json_object(d), "version_str", BITLBEE_VERSION);
121        json_object_set_number(json_object(d), "version", BITLBEE_VERSION_CODE);
122        json_array_append_value(d);
123        char *s = json_serialize_to_string(rpc);
124
125        if ((st = write(fd, s, strlen(s))) != strlen(s)) {
126                // LOG ERROR
127                return;
128        }
129        g_free(s);
130
131        char *resp = NULL;
132        int bufsize = 4096, resplen = 0;
133        JSON_Value *parsed;
134        do {
135                fd_set rfds;
136                struct timeval to;
137
138                FD_ZERO(&rfds);
139                FD_SET(fd, &rfds);
140                to.tv_sec = 1;
141                to.tv_usec = 0;
142                st = select(fd + 1, &rfds, NULL, NULL, &to);
143
144                if (st == 0) {
145                        // LOG ERROR
146                        return;
147                }
148               
149                if (resplen >= bufsize)
150                        bufsize *= 2;
151                resp = g_realloc(resp, bufsize + 1);
152                st = read(fd, resp + resplen, bufsize - resplen);
153                if (st == -1) {
154                        if (sockerr_again())
155                                continue;
156                        // LOG ERROR
157                        return;
158                }
159                resplen += st;
160                resp[resplen] = '\0';
161        }
162        while (!(parsed = json_parse_string(resp)));
163
164        JSON_Object *isup = json_object_get_object(json_object(parsed), "result");
165        if (isup == NULL) {
166                // LOG ERROR
167                return;
168        }
169
170        struct prpl *ret = g_new0(struct prpl, 1);
171       
172        JSON_Array *methods_a = json_object_get_array(isup, "methods");
173        GHashTable *methods = g_hash_table_new();
174        int i;
175        for (i = 0; i < json_array_get_count(methods_a); i++)
176                g_hash_table_add(methods, json_array_get_string(methods_a, i));
177
178        RPC_ADD_FUNC(login);
179        RPC_ADD_FUNC(chat_msg);
180       
181        g_hash_table_free(methods);
182
183        // TODO: Property for a few standard nickcmp implementations.
184       
185        JSON_Array *settings = json_object_get_array(isup, "settings");
186        for (i = 0; i < json_array_get_count(settings); i++) {
187                JSON_Object *set = json_array_get_object(settings, i);
188                // set..name, set..type, set..default, set..flags ?
189        }
190
191        ret->name = g_strdup(json_object_get_string(isup, "name"));
192
193        struct rpc_protocol *proto_data = g_new0(struct rpc_protocol, 1);
194        proto_data->addr = g_memdup(address, addrlen);
195        proto_data->addrlen = addrlen;
196        ret->data = proto_data;
197
198        register_protocol(ret);
199}
200
201void rpc_initmodule() {
202}
203
Note: See TracBrowser for help on using the repository browser.