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); }
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); } }
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; } }