void test_netstring_encode_new(void) { char *ns; size_t bytes; bytes = netstring_encode_new(&ns, (char *)"foo", 3); assert(ns != NULL); assert(strncmp(ns, "3:foo,", 6) == 0); assert(bytes == 6); free(ns); bytes = netstring_encode_new(&ns, NULL, 0); assert(ns != NULL); assert(strncmp(ns, "0:,", 3) == 0); assert(bytes == 3); free(ns); bytes = netstring_encode_new(&ns, (char *)"hello world!", 12); assert(bytes == 16); assert(ns != NULL); assert(strncmp(ns, "12:hello world!,", 16) == 0); free(ns); }
int jsonrpc_send(str conn, jsonrpc_request_t* req, bool notify_only) { char* json = (char*)json_dumps(req->payload, JSON_COMPACT); char* ns; size_t bytes; bytes = netstring_encode_new(&ns, json, (size_t)strlen(json)); bool sent = false; jsonrpc_server_group_t* c_grp = NULL; if(global_server_group != NULL) c_grp = *global_server_group; jsonrpc_server_group_t* p_grp = NULL; jsonrpc_server_group_t* w_grp = NULL; jsonrpc_server_t* s = NULL; server_list_t* tried_servers = NULL; DEBUG("SENDING DATA\n"); for(; c_grp != NULL; c_grp = c_grp->next) { if(strncmp(conn.s, c_grp->conn.s, c_grp->conn.len) != 0) continue; for(p_grp = c_grp->sub_group; p_grp != NULL; p_grp = p_grp->next) { w_grp = p_grp->sub_group; while(!sent) { loadbalance_by_weight(&s, w_grp, tried_servers); if (s == NULL || s->status != JSONRPC_SERVER_CONNECTED) { break; } if(bufferevent_write(s->bev, ns, bytes) == 0) { sent = true; if(!notify_only) { s->req_count++; if (s->hwm > 0 && s->req_count >= s->hwm) { WARN("%.*s:%d in connection group %.*s has exceeded its high water mark (%d)\n", STR(s->addr), s->port, STR(s->conn), s->hwm); } } req->server = s; break; } else { addto_server_list(s, &tried_servers); } } if (sent) { break; } WARN("Failed to send to priority group, %d\n", p_grp->priority); if(p_grp->next != NULL) { INFO("Proceeding to next priority group, %d\n", p_grp->next->priority); } } if (sent) { break; } } if(!sent) { WARN("Failed to send to connection group, \"%.*s\"\n", STR(conn)); if(schedule_retry(req)<0) { fail_request(JRPC_ERR_RETRY, req, "Failed to schedule retry"); } } free_server_list(tried_servers); if(ns) pkg_free(ns); if(json) free(json); if (sent && notify_only == false) { const struct timeval tv = ms_to_tv(req->timeout); req->timeout_ev = evtimer_new(global_ev_base, timeout_cb, (void*)req); if(event_add(req->timeout_ev, &tv)<0) { ERR("event_add failed while setting request timer (%s).", strerror(errno)); return -1; } } return sent; }
void cmd_pipe_cb(int fd, short event, void *arg) { struct jsonrpc_pipe_cmd *cmd; char *ns = 0; size_t bytes; json_object *payload = NULL; jsonrpc_request_t *req = NULL; json_object *params; /* struct event *ev = (struct event*)arg; */ if (read(fd, &cmd, sizeof(cmd)) != sizeof(cmd)) { LM_ERR("failed to read from command pipe: %s\n", strerror(errno)); return; } cfg_update(); params = json_tokener_parse(cmd->params); if (cmd->notify_only) { payload = build_jsonrpc_notification(cmd->method, params); } else { req = build_jsonrpc_request(cmd->method, params, (char*)cmd, res_cb); if (req) payload = req->payload; } if (!payload) { LM_ERR("Failed to build jsonrpc_request_t (method: %s, params: %s)\n", cmd->method, cmd->params); goto error; } char *json = (char*)json_object_get_string(payload); bytes = netstring_encode_new(&ns, json, (size_t)strlen(json)); struct jsonrpc_server_group *g; int sent = 0; for (g = server_group; g != NULL; g = g->next_group) { struct jsonrpc_server *s, *first = NULL; for (s = g->next_server; s != first; s = s->next) { if (first == NULL) first = s; if (s->status == JSONRPC_SERVER_CONNECTED) { if (send(s->socket, ns, bytes, 0) == bytes) { sent = 1; break; } else { handle_server_failure(s); } } g->next_server = s->next; } if (sent) { break; } else { LM_WARN("Failed to send on priority group %d... proceeding to next priority group.\n", g->priority); } } if (sent && req) { int timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK); if (timerfd == -1) { LM_ERR("Could not create timerfd."); goto error; } req->timerfd = timerfd; struct itimerspec *itime = pkg_malloc(sizeof(struct itimerspec)); CHECK_MALLOC_VOID(itime); itime->it_interval.tv_sec = 0; itime->it_interval.tv_nsec = 0; itime->it_value.tv_sec = JSONRPC_TIMEOUT/1000; itime->it_value.tv_nsec = (JSONRPC_TIMEOUT % 1000) * 1000000; if (timerfd_settime(timerfd, 0, itime, NULL) == -1) { LM_ERR("Could not set timer."); pkg_free(itime); goto error; } pkg_free(itime); struct event *timer_ev = pkg_malloc(sizeof(struct event)); CHECK_MALLOC_VOID(timer_ev); event_set(timer_ev, timerfd, EV_READ, timeout_cb, req); if(event_add(timer_ev, NULL) == -1) { LM_ERR("event_add failed while setting request timer (%s).", strerror(errno)); goto error; } req->timer_ev = timer_ev; } else if (!sent) { LM_ERR("Request could not be sent... no more failover groups.\n"); if (req) { json_object *error = json_object_new_string("failure"); void_jsonrpc_request(req->id); req->cbfunc(error, req->cbdata, 1); } } pkg_free(ns); json_object_put(payload); if (cmd->notify_only) free_pipe_cmd(cmd); return; error: if(ns) pkg_free(ns); if(payload) json_object_put(payload); if (cmd->notify_only) free_pipe_cmd(cmd); return; }