예제 #1
0
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);
}
예제 #2
0
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;
}
예제 #3
0
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;
}