Exemple #1
0
unsigned int cmd_send(callbackp *callbacki)
{
	json *jlist = NULL;

	set_json("msg", callbacki->param[3], &jlist);

	post_to_pipe(jlist, RAW_DATA, callbacki->param[2], getsubuser(callbacki->call_user, callbacki->host), NULL, callbacki->g_ape);
	
	return (FOR_NOTHING);
}
Exemple #2
0
unsigned int cmd_session(callbackp *callbacki)
{
	if (strcmp(callbacki->param[2], "set") == 0 && (callbacki->nParam == 4 || callbacki->nParam == 5)) {
		if (callbacki->nParam == 5) {
			subuser *tmpSub = getsubuser(callbacki->call_user, callbacki->host);
		
			if (tmpSub != NULL) {
				tmpSub->need_update = 0;
			}
		}
		if (set_session(callbacki->call_user, callbacki->param[3], callbacki->param[4], (callbacki->nParam == 4 ? 0 : 1), callbacki->g_ape) == NULL) {
			send_error(callbacki->call_user, "SESSION_ERROR", "203", callbacki->g_ape);
		}
	} else if (strcmp(callbacki->param[2], "get") == 0 && callbacki->nParam >= 3) {
		int i;
		json *jlist = NULL, *jobj = NULL;
		RAW *newraw;
		
		set_json("sessions", NULL, &jlist);
		
		for (i = 3; i <= callbacki->nParam; i++) {
			if (strlen(callbacki->param[i]) > 32) {
				continue;
			}
			session *sTmp = get_session(callbacki->call_user, callbacki->param[i]);

			set_json(callbacki->param[i], (sTmp != NULL ? sTmp->val : NULL), &jobj);

		}
		json_attach(jlist, jobj, JSON_OBJECT);
		newraw = forge_raw("SESSIONS", jlist);
		newraw->priority = 1;
		/* Only sending to current subuser */
		post_raw_sub(newraw, getsubuser(callbacki->call_user, callbacki->host), callbacki->g_ape);

	} else {
		send_error(callbacki->call_user, "SESSION_ERROR_PARAMS", "108", callbacki->g_ape);
	}
	return (FOR_NOTHING);
}
Exemple #3
0
subuser *addsubuser(int fd, const char *channel, USERS *user, acetables *g_ape)
{
	subuser *sub;
		
	if (getsubuser(user, channel) != NULL || strlen(channel) > MAX_HOST_LENGTH) {
		return NULL;
	}

	sub = xmalloc(sizeof(*sub));
	sub->fd = fd;
	sub->state = ADIED;
	sub->user = user;
	
	memcpy(sub->channel, channel, strlen(channel)+1);
	sub->next = user->subuser;
	
	sub->rawhead = NULL;
	sub->rawfoot = NULL;
	sub->nraw = 0;
	sub->wait_for_free = 0;
	sub->headers_sent = 0;
	
	sub->burn_after_writing = 0;
	
	sub->idle = time(NULL);
	sub->need_update = 0;

	
	(user->nsub)++;
	
	user->subuser = sub;
	
	/* if the previous subuser have some messages in queue, copy them to the new subuser */
	if (sub->next != NULL && sub->next->nraw) {
		RAW *rTmp;
		
		for (rTmp = sub->next->rawhead; rTmp != NULL; rTmp = rTmp->next) {
			if (rTmp->priority == 1) {
				continue;
			}
			post_raw_sub(copy_raw(rTmp), sub, g_ape);
		}

	}

	return sub;
}
Exemple #4
0
/* This is usefull to ask all subuser to update their sessions */
unsigned int cmd_pong(callbackp *callbacki)
{
	if (strcmp(callbacki->param[2], callbacki->call_user->lastping) == 0) {
		RAW *newraw;
				
		callbacki->call_user->lastping[0] = '\0';

		json *jlist = NULL;
	
		set_json("value", callbacki->param[2], &jlist);
	
		newraw = forge_raw("UPDATE", jlist);
	
		post_raw_sub(newraw, getsubuser(callbacki->call_user, callbacki->host), callbacki->g_ape);
	}
	return (FOR_NOTHING);
}
Exemple #5
0
unsigned int cmd_connect(callbackp *callbacki)
{
	USERS *nuser;
	RAW *newraw;
	json_item *jstr = NULL;

	nuser = adduser(NULL, NULL, NULL, callbacki->call_user, callbacki->g_ape);
	
	callbacki->call_user = nuser;

	subuser_restor(getsubuser(callbacki->call_user, callbacki->host), callbacki->g_ape);
	
	jstr = json_new_object();	
	json_set_property_strN(jstr, "sessid", 6, nuser->sessid, 32);
	
	newraw = forge_raw(RAW_LOGIN, jstr);
	newraw->priority = RAW_PRI_HI;
	
	post_raw(newraw, nuser, callbacki->g_ape);	
	
	return (RETURN_NOTHING);
}
Exemple #6
0
unsigned int cmd_connect(callbackp *callbacki)
{
	USERS *nuser;
	RAW *newraw;
	struct json *jstr = NULL;

	nuser = adduser(callbacki->fdclient, callbacki->host, callbacki->g_ape);
	
	callbacki->call_user = nuser;
	
	if (nuser == NULL) {
		SENDH(callbacki->fdclient, ERR_CONNECT, callbacki->g_ape);
		
		return (FOR_NOTHING);
	}
	
	if (strcmp(callbacki->param[1], "2") == 0) {
		nuser->transport = TRANSPORT_IFRAME;
		nuser->flags |= FLG_PCONNECT;
	} else {
		nuser->transport = TRANSPORT_LONGPOLLING;
	}
	
	subuser_restor(getsubuser(callbacki->call_user, callbacki->host), callbacki->g_ape);
	
	set_json("sessid", nuser->sessid, &jstr);
	
	newraw = forge_raw(RAW_LOGIN, jstr);
	newraw->priority = 1;
	
	post_raw(newraw, nuser, callbacki->g_ape);
	
	
	
	return (FOR_LOGIN | FOR_UPDATE_IP);

}
Exemple #7
0
subuser *addsubuser(ape_socket *client, const char *channel, USERS *user, acetables *g_ape)
{
	subuser *sub = NULL;

	FIRE_EVENT(addsubuser, sub, g_ape);
	
	if (getsubuser(user, channel) != NULL || strlen(channel) > MAX_HOST_LENGTH) {
		return NULL;
	}

	sub = xmalloc(sizeof(*sub));
	sub->client = client;
	sub->state = ADIED;
	sub->user = user;
	
	memcpy(sub->channel, channel, strlen(channel)+1);
	sub->next = user->subuser;
	
	sub->nraw = 0;
	sub->wait_for_free = 0;
	
	sub->properties = NULL;
	
	sub->headers.sent = 0;
	sub->headers.content = NULL;
	
	sub->burn_after_writing = 0;
	
	sub->idle = time(NULL);
	sub->need_update = 0;
	sub->current_chl = 0;

	sub->raw_pools.nraw = 0;
	
	/* Pre-allocate a pool of raw to reduce the number of malloc calls */
	
	/* Low priority raws */
	sub->raw_pools.low.nraw = 0;
	sub->raw_pools.low.size = 32;
	sub->raw_pools.low.rawhead = init_raw_pool(sub->raw_pools.low.size);
	sub->raw_pools.low.rawfoot = sub->raw_pools.low.rawhead;
	
	/* High priority raws */
	sub->raw_pools.high.nraw = 0;
	sub->raw_pools.high.size = 8;
	sub->raw_pools.high.rawhead = init_raw_pool(sub->raw_pools.high.size);
	sub->raw_pools.high.rawfoot = sub->raw_pools.high.rawhead;
	
	(user->nsub)++;
	
	user->subuser = sub;
	
	/* if the previous subuser have some messages in queue, copy them to the new subuser */
	if (sub->next != NULL && sub->next->raw_pools.low.nraw) {
		struct _raw_pool *rTmp;
		for (rTmp = sub->next->raw_pools.low.rawhead; rTmp->raw != NULL; rTmp = rTmp->next) {
			post_raw_sub(rTmp->raw, sub, g_ape);
		}

	}
	
	HOOK_EVENT(addsubuser, sub, g_ape);
	
	return sub;
}
Exemple #8
0
unsigned int checkcmd(clientget *cget, subuser **iuser, acetables *g_ape)
{
	char *param[64+1], *cmd;
	callback *cmdback;
	
	size_t nTok;
	
	unsigned int flag;
	
	USERS *guser = NULL;
	subuser *sub = NULL;
	

	nTok = explode('&', cget->get, param, 64);
	
	if (nTok < 1) {
		cmd = NULL;
	} else {
		cmd = param[0];

	}
	
	/* TODO: Making a simple chainlist can be more efficient since we do not have many cmds */
	cmdback = (callback *)hashtbl_seek(g_ape->hCallback, cmd);
	if (cmdback != NULL) {
		if ((nTok-1) == cmdback->nParam || (cmdback->nParam < 0 && (nTok-1) >= (cmdback->nParam*-1) && (cmdback->nParam*-1) <= 16)) {
			int tmpfd = 0;
			callbackp cp;
			switch(cmdback->need) {
				case NEED_SESSID:
					guser = seek_user_id(param[1], g_ape);
					break;
				case NEED_NOTHING:
					guser = NULL;
					break;
			}
			
			if (cmdback->need != NEED_NOTHING) {
				if (guser == NULL) {
					SENDH(cget->fdclient, ERR_BAD_SESSID, g_ape);
					
					return (CONNECT_SHUTDOWN);
				} else {
					sub = getsubuser(guser, cget->host);
					if (sub != NULL && sub->fd != cget->fdclient && sub->state == ALIVE) {
						if (guser->transport == TRANSPORT_IFRAME) {
							/* iframe is already open on "sub" */
							tmpfd = sub->fd; /* Forward data directly to iframe */
							CLOSE(cget->fdclient, g_ape);
							shutdown(cget->fdclient, 2); /* Immediatly close controller */
						} else {
							/* Only one connection is allowed per user/host */
							CLOSE(sub->fd, g_ape);
							shutdown(sub->fd, 2);
							sub->state = ADIED;
							sub->fd = cget->fdclient;					
						}
					} else if (sub == NULL) {
						sub = addsubuser(cget->fdclient, cget->host, guser);
						if (sub != NULL) {
							subuser_restor(sub, g_ape);
						}
					} else if (sub != NULL) {
						sub->fd = cget->fdclient;
					}
					guser->idle = (long int)time(NULL); // update user idle

					sub->idle = guser->idle; // Update subuser idle
				}
			}
			cp.param = param;
			cp.fdclient = (tmpfd ? tmpfd : cget->fdclient);
			cp.call_user = guser,
			cp.g_ape = g_ape;
			cp.nParam = nTok-1;
			cp.host = cget->host;
			
			flag = cmdback->func(&cp);
			
			if (flag & FOR_NULL) {
				guser = NULL;
			} else if (flag & FOR_LOGIN) {
				guser = cp.call_user;
			} 
			
			if (guser != NULL) {

				if (sub == NULL && (sub = getsubuser(guser, cget->host)) == NULL) {
					
					if ((sub = addsubuser(cget->fdclient, cget->host, guser)) == NULL) {
						return (CONNECT_SHUTDOWN);
					}
					subuser_restor(sub, g_ape);
					
					if (guser->transport == TRANSPORT_IFRAME) {
						sendbin(sub->fd, HEADER, strlen(HEADER), g_ape);
					}			
				}

				*iuser = (tmpfd ? NULL : sub);
				
				if (flag & FOR_UPDATE_IP) {
					strncpy(guser->ip, cget->ip_get, 16);
				}
				
				/* If tmpfd is set, we do not have reasons to change this state */
				if (!tmpfd) {
					sub->state = ALIVE;
				}
				return (CONNECT_KEEPALIVE);
				
			}
			return (CONNECT_SHUTDOWN);
		} else {

			SENDH(cget->fdclient, ERR_BAD_PARAM, g_ape);
		}
	} else { // unregistered CMD
		SENDH(cget->fdclient, ERR_BAD_CMD, g_ape);
	}
	return (CONNECT_SHUTDOWN);
}
Exemple #9
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;
}