Beispiel #1
0
oc::result<std::vector<std::string>> socket_read_string_array(int fd)
{
    OUTCOME_TRY(len, socket_read_int32(fd));
    if (len < 0) {
        return std::errc::bad_message;
    }

    std::vector<std::string> buf;
    buf.reserve(static_cast<size_t>(len));

    for (int32_t i = 0; i < len; ++i) {
        OUTCOME_TRY(str, socket_read_string(fd));
        buf.push_back(std::move(str));
    }

    return std::move(buf);
}
Beispiel #2
0
void controller_user_login(bmessage_t* pMsg)
{
	bresponse_t response = {0};
	trans_str_size_t len = TRANS_STR_LEN;
	char pwd[TRANS_STR_LEN] = {0};
	int uid = 0;
	char sql[200] = {0};
	char* username = NULL;
	BMYSQL_RES* bresult;
	int ret = 0;
	
	uid = socket_read_int(pMsg);
	socket_read_string(pMsg, pwd, &len);
	
	snprintf(sql, 199, "select `username` from `qgame_users` where `uid`=%d and `password`=\"%s\"", uid, pwd);
	printf("before bmysql_query_scalar\n");
	int ret = bmysql_query_scalar(sql, &username, bresult);
	
	if(ret == 0)
	{
		printf("user login bresult->id:%d\tpMsg:%p\n", bresult->id, pMsg);

		if(username == NULL)
		{
			response.code = ERROR_USER_LOGIN_FAIL;
		}
		else
		{
			socket_write_string(&response, username, strlen(username));
			socket_write_int(&response, uid);
			socket_write_string(&response, pwd, len);
		}

		socket_flush(pMsg, &response);
		bmysql_free_result(bresult);
	}
	else
	{
		printf("mysql query error:%d\n", ret);
	}
}
Beispiel #3
0
bool socket_read_string_array(int fd, std::vector<std::string> *result)
{
    int32_t len;
    if (!socket_read_int32(fd, &len)) {
        return false;
    }

    if (len < 0) {
        return false;
    }

    std::vector<std::string> buf(len);
    for (int32_t i = 0; i < len; ++i) {
        std::string temp;
        if (!socket_read_string(fd, &temp)) {
            return false;
        }
        buf[i] = std::move(temp);
    }

    result->swap(buf);
    return true;
}
/*
 * Maneja los requests que hacen los clientes.
 */
int
connection_client_handler(events_t *ev, event_t *event)
{
	client_t *client = client_get(event->fd);

	char *data =
	"ICY 200 OK\r\n"
	"icy-notice1: NOTICE 1\r\n"
	"icy-notice2: NOTICE 2\r\n"
	"icy-name: STATION NAME\r\n"
	"icy-genre: GENRE\r\n"
	"icy-url: http://localhost\r\n"
	"content-type: audio/mpeg\r\n"
	"icy-pub: 1\r\n"
	"icy-metaint: 0\r\n"
	"icy-br: 128\r\n"
	"\r\n";

	// TODO a buffer moverlo de aca, no tiene sentido alocarlo en la stack cada ves
	// que llamamos al event handler
	char buffer[512];

	if(event->event_mask & EVENT_READ)
	{
		// Evento de lectura, puede ser que se cerro el cliente
		// o que es el inicio de la conexion y estamos por
		// intercambiar headers.
		// Otra cosa es error, no esperada.

		// Esta funcion es llamada cada ves que hay un evento de lectura
		// es decir cuando uno de nuestros clientes nos envia algo.
		// Esto solo sucede al inicio de la conexion cuando el servidor y
		// el cliente intercambian headers con informacion sobre la proxima
		// conexion.
		//
		// Vamos a aceptar los clientes nuevos aca, a nivel ICECAST no nivel socket
		// es decir que vamos a crear las estructuras necesarias para
		// mantener la informacion sobre los clientes.
		// Tambien vamos a manejar las desconexiones. Estas las vamos a detectar
		// por que el socket al leer nos va a devolver 0 bytes.


		// Si el cliente estaba en estado WAITING lo proximo que tendria
		// que enviar son headers de ICECAST para establecer conexion.
		if(client->state == CLIENT_WAITING)
		{
			#ifdef DEBUG
			printf("[cliente=%d] connection_client_handler(EVENT_READ):CLIENT_WAITING\n", event->fd);
			#endif

			if(socket_read_string(event->fd, buffer, sizeof(buffer)) == -1)
			{
				perror("connection_client_handler():");
				return -1;
			}

			// Por ahora la verificacion es simple
			if(strcasestr(buffer, "icy-metadata: 1") == NULL)
			{
				#ifdef DEBUG
				fprintf(stderr, "[cliente=%d] Headers invalidos, desconectando\n", event->fd);
				#endif

				event_del(ev, event->fd);
				socket_close(event->fd);
				client_destroy(client);
				server.clients--;

				return 0;
			}

			// Si esta todo bien seteamos como empezando la conexion
			client->state = CLIENT_STARTING;

			return 0;
		}
		else
		{
			// Manejar desconecciones
			if(socket_read_string(event->fd, buffer, sizeof(buffer)) == 0)
			{
				#ifdef DEBUG
				fprintf(stderr, "[cliente=%d] Desconectando cliente\n", event->fd);
				#endif

				event_del(ev, event->fd);
				socket_close(event->fd);
				client_destroy(client);
				server.clients--;

				return 0;
			}

			#ifdef DEBUG
			fprintf(stderr, "[cliente=%d] Invalid read\n%s\n", event->fd, buffer);
			#endif
		}
	}
	else if(event->event_mask & EVENT_WRITE)
	{
		char *buffer;
		int ret;

		switch(client->state)
		{
			case CLIENT_STARTING:
				#ifdef DEBUG
				printf("[cliente=%d] connection_client_handler(EVENT_WRITE):CLIENT_STARTING\n",
						event->fd);
				#endif

				if(socket_write_all(event->fd, data, strlen(data)) == -1)
				{
					perror("connection_client_handler():");
					return -1;
				}

				client->state = CLIENT_ACTIVE;
				break;
			case CLIENT_ACTIVE:
				// Servir con contenido al cliente.
				#ifdef DEBUG
				fprintf(stderr, "[cliente=%d] connection_client_handler(EVENT_WRITE):CLIENT_ACTIVE\n",
						event->fd);
				#endif

				ret = stream_read(server.stream, client->offset,
						server.buffer_size, &buffer);

				if(ret == -1)
				{
					perror("connection_client_handler():");
					return -1;
				}

				#ifdef BANDWIDTH_THROTTLING
				#include <sys/time.h>

				struct timeval now;
				if(gettimeofday(&now, NULL) == -1)
				{
					perror("connection_client_handler():");
					return -1;
				}

				static inline int
				difftime(struct timeval *t1, struct timeval *t2, useconds_t interval)
				{
					// Si hay diferencia de segundos devolver que si paso el
					// intervalo ya que este es medido en usecs.
					if(t2->tv_sec - t1->tv_sec)
						return 1;

					// si la diff entre usecs es mayor o igual que interval
					// podemos enviar
					return ((t2->tv_usec - t1->tv_usec) >= interval) ? 1 : 0;
				}

				if(!difftime(&client->last_write_ts, &now, interval))
				{
					// El intervalo no paso, hacemos que se sirva otro socket
					return 0;
				}
				#endif

				// Podriamos haber usado socket_write_all pero no me convence, por que
				// si fallo, es por algo y de ultima eso lo manejamos con el offset del cliente
				// y los datos se los reenviamos.
				ret = socket_write(event->fd, buffer, server.buffer_size);
				if(ret == -1)
				{
					perror("connection_client_handler():");
					return -1;
				}

				#ifdef BANDWIDTH_THROTTLING
				if(gettimeofday(&client->last_write_ts, NULL) == -1)
				{
					perror("connection_client_handler():");
					return -1;
				}
				#endif


				client->offset += ret;

				// Por ahora reiniciamos el streaming.
				if(client->offset == server.stream->size)
				{
					#ifdef DEBUG
					fprintf(stderr, "[cliente=%d] connection_client_handler(CLIENT_ACTIVE):EVENT_WRITE: Se llego al final del stream, reiniciando.\n"
							, event->fd);
					#endif

					client->offset = 0;
				}

				break;
			default:
				break;
		}
	}