Esempio n. 1
0
static void
event_cb (uv_udp_t *req, ssize_t nread, const uv_buf_t *buf,
          const struct sockaddr *addr, unsigned flags)
{
  Event *event = (Event *) req;
  Server *server = SERVER_FROM_EVENT (event);
  // Time timestamp = time_now ();

  debug ("\"%.*s\"", (int) nread, buf->base);

  if (nread == 0)
    goto done;

  if (nread < 0) {
    // TODO: log error
    uv_close ((uv_handle_t *) req, NULL);
    goto reject;
  }

  // TODO: log ...
  // char sender[17] = { 0 };
  // uv_ip4_name((const struct sockaddr_in*) addr, sender, 16);

  debug ("parsing json");
  if (json_parse_src (event->json, buf->base, nread)
      != JSON_OK)
    goto reject;

  Status stat = G_OK;
  JsonVal *val;

  val = json_lookup (event->json, "event", 5);
  if (val->type != JSON_STRING)
    // reject for invalid event type
    goto reject;

  EventKey *e = map_get (event_map, val->as_string, val->size);
  if (e) {
    debug ("handling event: %.*s", (int) val->size, val->as_string);
    e->handler (event);
  }

done:
  debug ("done");
  // send Ack Response
  goto finally;

reject:
  debug ("reject");
  // send Reject Response
  goto finally;

finally:
  event->base_alloc = false;
  return;
}
Esempio n. 2
0
int process_cmd(json_item *ijson, struct _cmd_process *pc, subuser **iuser, acetables *g_ape)
{
	callback *cmdback, tmpback = {handle_bad_cmd, NEED_NOTHING};
	json_item *rjson = json_lookup(ijson->jchild.child, "cmd"), *jchl;
	subuser *sub = pc->sub;
	unsigned int flag;
	unsigned short int attach = 1;

	if (rjson != NULL && rjson->jval.vu.str.value != NULL) {
		callbackp cp;
		cp.client = NULL;
		cp.cmd 	= rjson->jval.vu.str.value;
		cp.data = NULL;
		cp.hlines = NULL;
		
		json_item *jsid;
		
		if ((cmdback = (callback *)hashtbl_seek(g_ape->hCallback, rjson->jval.vu.str.value)) == NULL) {
			cmdback = &tmpback;
		}
		
		if ((pc->guser == NULL && (jsid = json_lookup(ijson->jchild.child, "sessid")) != NULL && jsid->jval.vu.str.value != NULL)) {
			pc->guser = seek_user_id(jsid->jval.vu.str.value, g_ape);
		}

		if (cmdback->need != NEED_NOTHING || pc->guser != NULL) { // We process the connection like a "NEED_SESSID" if the user provide its key

			if (pc->guser == NULL) {
				
				RAW *newraw;
				json_item *jlist = json_new_object();

				json_set_property_strZ(jlist, "code", "004");
				json_set_property_strZ(jlist, "value", "BAD_SESSID");

				newraw = forge_raw(RAW_ERR, jlist);
				
				send_raw_inline(pc->client, pc->transport, newraw, g_ape);

				return (CONNECT_SHUTDOWN);
			} else if (sub == NULL) {
				
				sub = getsubuser(pc->guser, pc->host);
				if (sub != NULL && sub->client->fd != pc->client->fd && sub->state == ALIVE) {
					/* The user open a new connection while he already has one openned */
					struct _transport_open_same_host_p retval = transport_open_same_host(sub, pc->client, pc->guser->transport);				
			
					if (retval.client_close != NULL) {
						// Send CLOSE if no response has been sent yet
						if (!sub->headers.sent) {
							RAW *newraw;
							json_item *jlist = json_new_object();

							json_set_property_strZ(jlist, "value", "null");

							newraw = forge_raw("CLOSE", jlist);

							send_raw_inline((retval.client_close->fd == pc->client->fd ? pc->client : sub->client), pc->transport, newraw, g_ape);
						}
						
						// It's not safe to leave the subuser pointer in co->attach anymore
						// since subuser could subsequently be deleted, leaving a pointer into free heap.
						// So, let this socket finish up on its own and pretend its already finished.

						sub->state = ADIED;
						sub->headers.sent = 0;
						http_headers_free(sub->headers.content);
						sub->headers.content = NULL;
						sub->burn_after_writing = 0;

						g_ape->co[retval.client_close->fd]->attach = NULL;
						safe_shutdown(retval.client_close->fd, g_ape);
					}
					sub->client = cp.client = retval.client_listener;
					sub->state = retval.substate;
					attach = retval.attach;
			
				} else if (sub == NULL) {
					sub = addsubuser(pc->client, pc->host, pc->guser, g_ape);
					if (sub != NULL) {
						subuser_restor(sub, g_ape);
					}
				} else if (sub != NULL) {
					sub->client = pc->client;
				}
				pc->guser->idle = (long int)time(NULL); // update user idle

				sub->idle = pc->guser->idle; // Update subuser idle
				
			}

		}
		
		if (pc->guser != NULL && sub != NULL && (jchl = json_lookup(ijson->jchild.child, "chl")) != NULL /*&& jchl->jval.vu.integer_value > sub->current_chl*/) {
			sub->current_chl = jchl->jval.vu.integer_value;
		}
		#if 0 
		else if (pc->guser != NULL && sub != NULL) {
			/* if a bad challenge is detected, we are stoping walking on cmds */
			send_error(pc->guser, "BAD_CHL", "250", g_ape);

			sub->state = ALIVE;
			
			return (CONNECT_KEEPALIVE);
		}
		#endif
					
		cp.param = json_lookup(ijson->jchild.child, "params");
		cp.client = (cp.client != NULL ? cp.client : pc->client);
		cp.call_user = pc->guser;
		cp.call_subuser = sub;
		cp.g_ape = g_ape;
		cp.host = pc->host;
		cp.ip = pc->ip;
		cp.chl = (sub != NULL ? sub->current_chl : 0);
		cp.transport = pc->transport;
		cp.hlines = pc->hlines;
		
		/* Little hack to access user object on connect hook callback (preallocate an user) */
		if (strncasecmp(cp.cmd, "CONNECT", 7) == 0 && cp.cmd[7] == '\0') {
			pc->guser = cp.call_user = adduser(cp.client, cp.host, cp.ip, NULL, g_ape);
			pc->guser->transport = pc->transport;
			sub = cp.call_subuser = cp.call_user->subuser;
		}
		
		if ((flag = call_cmd_hook(cp.cmd, &cp, g_ape)) == RETURN_CONTINUE) {
			flag = cmdback->func(&cp);
		}
		
		if (flag & RETURN_NULL) {
			pc->guser = NULL;
		} else if (flag & RETURN_BAD_PARAMS) {
			RAW *newraw;
			json_item *jlist = json_new_object();
			
			if (cp.chl) {
				json_set_property_intN(jlist, "chl", 3, cp.chl);
			}
			json_set_property_strZ(jlist, "code", "001");
			json_set_property_strZ(jlist, "value", "BAD_PARAMS");

			newraw = forge_raw(RAW_ERR, jlist);
			
			if (cp.call_user != NULL) {
				//cp.call_user->istmp = 0;
				if (sub == NULL) {
					sub = getsubuser(pc->guser, pc->host);	
				}
				post_raw_sub(newraw, sub, g_ape);
			} else {
				send_raw_inline(pc->client, pc->transport, newraw, g_ape);
			}
			
			//guser = NULL;
		} else if (flag & RETURN_BAD_CMD) {
			RAW *newraw;
			json_item *jlist = json_new_object();

			if (cp.chl) {
				json_set_property_intN(jlist, "chl", 3, cp.chl);
			}
			json_set_property_strZ(jlist, "code", "003");
			json_set_property_strZ(jlist, "value", "BAD_CMD");

			newraw = forge_raw(RAW_ERR, jlist);
			
			if (cp.call_user != NULL) {	
				if (sub == NULL) {
					sub = getsubuser(pc->guser, pc->host);	
				}
				post_raw_sub(newraw, sub, g_ape);
			} else {
				send_raw_inline(pc->client, pc->transport, newraw, g_ape);
			}					
		}

		if (pc->guser != NULL) {
			if (sub == NULL) {
				sub = getsubuser(pc->guser, pc->host);	
			}
			if (iuser != NULL) {
				*iuser = (attach ? sub : NULL);
			}
			/* If tmpfd is set, we do not have any reasons to change its state */
			sub->state = ALIVE;
			
			if (flag & RETURN_HANG || flag & RETURN_BAD_PARAMS) {
				return (CONNECT_KEEPALIVE);
			}
			
		} else if (flag & RETURN_HANG) {
			/* Doesn't need sessid */
			return (CONNECT_KEEPALIVE);
		} else {
			return (CONNECT_SHUTDOWN);
		}
	} else {

		RAW *newraw;
		json_item *jlist = json_new_object();

		json_set_property_strZ(jlist, "code", "003");
		json_set_property_strZ(jlist, "value", "NO_CMD");

		newraw = forge_raw(RAW_ERR, jlist);

		send_raw_inline(pc->client, pc->transport, newraw, g_ape);
		//printf("Cant find %s\n", rjson->jval.vu.str.value);
		return (CONNECT_SHUTDOWN);
	}
	
	return -1;
}