- Timestamp:
- 2015-04-03T23:20:57Z (10 years ago)
- Children:
- bc73e2ba
- Parents:
- 9ae7332
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
protocols/rpc/rpc.c
r9ae7332 r578790e 25 25 struct groupchat *gc; 26 26 }; 27 28 static 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 } 27 37 28 38 static JSON_Value *rpc_out_new(const char *method, JSON_Array **params_) { … … 89 99 struct rpc_connection *rd = ic->proto_data = g_new0(struct rpc_connection, 1); 90 100 struct rpc_plugin *pd = acc->prpl->data; 101 imcb_log(ic, "Connecting to RPC server"); 91 102 rd->fd = socket(pd->addr->sa_family, SOCK_STREAM, 0); 92 103 sock_make_nonblocking(rd->fd); … … 229 240 } 230 241 231 static struct groupchat *rpc_groupchat_new(struct im_connection *ic, const char *handle) { 242 static struct rpc_groupchat *rpc_groupchat_new(struct im_connection *ic, const char *handle) { 243 struct rpc_connection *rd = ic->proto_data; 232 244 struct groupchat *gc = imcb_chat_new(ic, handle); 233 245 struct rpc_groupchat *rc = gc->data = g_new0(struct rpc_groupchat, 1); 234 rc->id = next_rpc_id ;246 rc->id = next_rpc_id++; 235 247 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 252 static 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) 238 267 239 268 static struct groupchat *rpc_chat_with(struct im_connection *ic, char *who) { 240 269 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); 243 271 json_array_append_number(params, rc->id); 244 272 json_array_append_string(params, who); 245 273 rpc_send(ic, rpc); 246 274 247 return gc;275 return rc->gc; 248 276 } 249 277 … … 251 279 const char *password, set_t **sets) { 252 280 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); 255 282 json_array_append_number(params, rc->id); 256 283 json_array_append_string(params, room); … … 260 287 rpc_send(ic, rpc); 261 288 262 return gc;289 return rc->gc; 263 290 } 264 291 … … 271 298 } 272 299 273 static gbooleanrpc_cmd_in(struct im_connection *ic, const char *cmd, JSON_Array *params);300 static JSON_Value *rpc_cmd_in(struct im_connection *ic, const char *cmd, JSON_Array *params); 274 301 275 302 static gboolean rpc_in(struct im_connection *ic, JSON_Object *rpc) { 276 JSON_Object *res = json_object_get_object(rpc, "result");277 303 const char *cmd = json_object_get_string(rpc, "method"); 278 304 JSON_Value *id = json_object_get_value(rpc, "id"); 279 305 JSON_Array *params = json_object_get_array(rpc, "params"); 280 306 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) { 282 311 imcb_log(ic, "Received invalid JSON-RPC object."); 283 312 imc_logout(ic, TRUE); … … 285 314 } 286 315 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 } 293 322 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 else297 json_object_set_value(json_object(resp), "error", json_value_init_object());298 323 return rpc_send(ic, resp); 299 324 } 325 326 return TRUE; 300 327 } 301 328 … … 313 340 314 341 if (st == 0 || (st == -1 && !(sockerr_again() || errno == EAGAIN))) { 315 imcb_log(ic, " Read error");342 imcb_log(ic, "Lost RPC connection"); 316 343 imc_logout(ic, TRUE); 317 344 return FALSE; … … 345 372 } 346 373 347 static voidrpc_imcb_log(struct im_connection *ic, void *func_, JSON_Array *params) {348 void (*func)(struct im_connection*, c har*, ...) = func_;374 static JSON_Value *rpc_imcb_log(struct im_connection *ic, void *func_, JSON_Array *params) { 375 void (*func)(struct im_connection*, const char*, ...) = func_; 349 376 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 380 static JSON_Value *rpc_imcb_connected(struct im_connection *ic, void *func_, JSON_Array *params) { 353 381 void (*func)(struct im_connection*) = func_; 354 382 func(ic); 355 } 356 357 static void rpc_imc_logout(struct im_connection *ic, void *func_, JSON_Array *params) { 383 return NULL; 384 } 385 386 static JSON_Value *rpc_imc_logout(struct im_connection *ic, void *func_, JSON_Array *params) { 358 387 void (*func)(struct im_connection*, gboolean) = func_; 359 388 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 392 static JSON_Value *rpc_imcb_add_buddy(struct im_connection *ic, void *func_, JSON_Array *params) { 363 393 void (*func)(struct im_connection*, const char*, const char*) = func_; 364 394 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 398 static JSON_Value *rpc_imcb_buddy_status(struct im_connection *ic, void *func_, JSON_Array *params) { 368 399 void (*func)(struct im_connection*, const char*, int, const char*, const char*) = func_; 369 400 func(ic, json_array_get_string(params, 0), json_array_get_number(params, 1), 370 401 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 405 static JSON_Value *rpc_imcb_buddy_times(struct im_connection *ic, void *func_, JSON_Array *params) { 374 406 void (*func)(struct im_connection*, const char*, int, int) = func_; 375 407 func(ic, json_array_get_string(params, 0), json_array_get_number(params, 1), 376 408 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 412 static JSON_Value *rpc_imcb_buddy_msg(struct im_connection *ic, void *func_, JSON_Array *params) { 380 413 void (*func)(struct im_connection*, const char*, const char*, int, int) = func_; 381 414 func(ic, json_array_get_string(params, 0), json_array_get_string(params, 1), 382 415 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 419 static 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_; 387 421 func(ic, (char*) json_array_get_string(params, 0), json_array_get_number(params, 1)); 422 return NULL; 423 } 424 425 static 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 432 static 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 440 static 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 449 static 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 457 static 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 466 static 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 474 static 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; 388 481 } 389 482 … … 391 484 char *name; 392 485 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); 394 487 char args[8]; 395 488 }; 396 489 397 490 static const struct rpc_in_method methods[] = { 491 /* All these RPCs are equivalent of BitlBee C functions but with the 492 * struct im_connection* removed. */ 398 493 { "imcb_log", imcb_log, rpc_imcb_log, "s" }, 399 494 { "imcb_error", imcb_error, rpc_imcb_log, "s" }, … … 409 504 { "imcb_buddy_msg", imcb_buddy_msg, rpc_imcb_buddy_msg, "ssnn" }, 410 505 { "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 411 518 { NULL }, 412 519 }; 413 520 414 static gbooleanrpc_cmd_in(struct im_connection *ic, const char *cmd, JSON_Array *params) {521 static JSON_Value *rpc_cmd_in(struct im_connection *ic, const char *cmd, JSON_Array *params) { 415 522 int i; 416 523 … … 419 526 if (json_array_get_count(params) != strlen(methods[i].args)) { 420 527 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"); 422 529 } 423 530 int j; … … 445 552 // This error sucks, but just get your types right! 446 553 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"); 448 555 } 449 556 } 450 methods[i].wfunc(ic, methods[i].func, params); 451 return TRUE; 557 return methods[i].wfunc(ic, methods[i].func, params); 452 558 } 453 559 } 454 return FALSE;560 return jsonrpc_error(ENOSYS, "Function not implemented"); 455 561 } 456 562 … … 558 664 // TODO: Property for a few standard nickcmp implementations. 559 665 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 560 672 JSON_Array *settings = json_object_get_array(isup, "settings"); 561 673 for (i = 0; i < json_array_get_count(settings); i++) { … … 563 675 // set..name, set..type, set..default, set..flags ? 564 676 } 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;572 677 573 678 register_protocol(ret);
Note: See TracChangeset
for help on using the changeset viewer.