static void read_request(struct server *s, struct client *c, struct frame_buffers *fbs) { size_t len; char buf[SERVER_BUFFER_SIZE]; memset(buf, 0, sizeof(buf)); if (!c->request_received) { if ((len = client_read(c, buf, sizeof(buf))) < 1) { if (errno == EINTR) { return; } // len == 0 means that the client has disconnected // len == -1 means an error occured return remove_client(s, c); } c->last_communication = gettime(); // Check if we have the whole thing strncpy(&c->request_headers[c->request_header_size], buf, MAX_REQUEST_HEADER_SIZE - c->request_header_size); c->request_header_size += len; if (strstr(c->request_headers, "\r\n\r\n") != NULL) { c->request_received = 1; } } // Parse request headers if (c->request_received && c->request == REQUEST_INCOMPLETE) { handle_request(s, c, fbs); } }
static gboolean client_socket_io_handler (GIOChannel * channel, GIOCondition condition, gpointer user_data) { BtPlaybackControllerSocket *self = BT_PLAYBACK_CONTROLLER_SOCKET (user_data); gboolean res = TRUE; gchar *cmd, *reply; GST_INFO ("client io handler : %d", condition); if (condition & (G_IO_IN | G_IO_PRI)) { if ((cmd = client_read (self))) { if ((reply = client_cmd_parse_and_process (self, cmd))) { if (!client_write (self, reply)) { res = FALSE; } g_free (reply); } g_free (cmd); } else res = FALSE; } if (condition & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) { res = FALSE; } if (!res) { GST_INFO ("closing client connection"); self->priv->master_source = 0; } return res; }
/* * Called on OP_READ request on the controller */ void controller_read(int *backend_socket, int client_socket, struct op_hdr get_hdr) { int len = -1, len2 = -1; int fd = -1; // FD int client_size = -1; // buffer on client side struct op_hdr put_hdr; void *ptr = NULL; // init put_hdr = get_hdr; fd = get_hdr.p1; client_size = get_hdr.p2; printf("\tRead on FD: %d\n", fd); /* Send Read file to backend server */ MALLOC(ptr, client_size); len2 = client_read(*backend_socket, fd, (void *)ptr, client_size); /* Reply */ put_hdr.p1 = len2; WRITE_SOC(len, client_socket, &put_hdr, HDR_SIZE); /* Send the data */ WRITE_SOC(len, client_socket, ptr, len2); free(ptr); printf("\tSent file of size: %d\n", len2); }
/* * Find the client definition. */ static rlm_rcode_t mod_authorize(UNUSED void *instance, REQUEST *request) { size_t length; const char *value; CONF_PAIR *cp; RADCLIENT *c; char buffer[2048]; /* * Ensure we're only being called from the main thread, * with fake packets. */ if ((request->packet->src_port != 0) || (request->packet->vps != NULL) || (request->parent != NULL)) { RDEBUG("Improper configuration"); return RLM_MODULE_NOOP; } if (!request->client || !request->client->cs) { RDEBUG("Unknown client definition"); return RLM_MODULE_NOOP; } cp = cf_pair_find(request->client->cs, "directory"); if (!cp) { RDEBUG("No directory configuration in the client"); return RLM_MODULE_NOOP; } value = cf_pair_value(cp); if (!value) { RDEBUG("No value given for the directory entry in the client."); return RLM_MODULE_NOOP; } length = strlen(value); if (length > (sizeof(buffer) - 256)) { RDEBUG("Directory name too long"); return RLM_MODULE_NOOP; } memcpy(buffer, value, length + 1); ip_ntoh(&request->packet->src_ipaddr, buffer + length, sizeof(buffer) - length - 1); /* * Read the buffer and generate the client. */ c = client_read(buffer, (request->client->server != NULL), TRUE); if (!c) return RLM_MODULE_FAIL; /* * Replace the client. This is more than a bit of a * hack. */ request->client = c; return RLM_MODULE_OK; }
void MainWindow::on_test_90_2_clicked() { struct fileinfo finfo = { finfo.copysize=1, finfo.filetype=NORMAL_FILE, finfo.blocklength=BLOCKLENGTH, }; memcpy(finfo.name,"test_90_2",100); long long testfid = client_create(&finfo); int testfd = client_open(testfid,O_READ); client_close(testfd); // char buff[BUFFSIZE]; int buffSize = atoi(ui->lineEdit_buffSize->text().toAscii()); char* buff = new char [buffSize*1024*1024]; int result = client_read(testfd,buff,(buffSize*1024*1024)*sizeof(char)); qDebug()<<result; if(result == -1 and testfd != -1){ char name1[100]; int errcode = getlasterror(testfd,name1,100); qDebug()<<"ERROR:"<<errcode<<name1; if(errcode == 102){ ui->textEdit->append(QString::number(lineCount) + " -----> read to the closed file test OK"); lineCount++; } else{ ui->textEdit->append(QString::number(lineCount) + " -----> read to the closed file test FAIL"); lineCount++; } } delete [] buff; }
// read from the client until there is a whole line in the buffer int client_read_line(int fd, char * buf, int * buffer_pos) { while ((strstr(buf, "\r\n") == NULL) && (strstr(buf, "\n") == NULL)) { int res = client_read(fd, buf, buffer_pos); if (res == -1) return -1; } return 0; }
// main client handler procedure, runs in its own thread void * thread_proc(void * param) { CLIENT_INFO client_info; memset(&client_info, 0, sizeof(client_info)); client_info.fd = (int)param; strcpy(client_info.dir, "/"); send_code(client_info.fd, 220); while (1) { int result = client_read(client_info.fd, client_info.buf, &client_info.buffer_pos); if (result == -1) break; while (client_info.buffer_pos >= 4) { char line[BUFFER_SIZE] = { 0 }; if (compare_command(client_info.buf, "USER")) command_user(&client_info); else if (compare_command(client_info.buf, "PASS")) command_pass(&client_info); else if (compare_command(client_info.buf, "PWD")) command_pwd(&client_info); else if (compare_command(client_info.buf, "PORT")) command_port(&client_info); else if (compare_command(client_info.buf, "PASV")) command_pasv(&client_info); else if (compare_command(client_info.buf, "LIST")) command_list(&client_info); else if (compare_command(client_info.buf, "CWD")) command_cwd(&client_info); else if (compare_command(client_info.buf, "RETR")) command_retr(&client_info); else if (compare_command(client_info.buf, "NOOP")) command_noop(&client_info); else if (compare_command(client_info.buf, "SYST")) command_syst(&client_info); else if (compare_command(client_info.buf, "TYPE")) command_type(&client_info); else if (compare_command(client_info.buf, "QUIT")) { get_line(client_info.fd, line, client_info.buf, &client_info.buffer_pos); send_code(client_info.fd, 221); close(client_info.fd); client_info.fd = 0; return NULL; } else { get_line(client_info.fd, line, client_info.buf, &client_info.buffer_pos); send_code(client_info.fd, 500); } } } if (client_info.fd != 0) { close(client_info.fd); client_info.fd = 0; } return NULL; }
void SFSUnix::checkSocket() { for (int i = 0; i < MAX_FD; i++) { if (FD_ISSET(i, &_fd_read)) { if (_e.fd_type[i] == FD_SERVER) server_read(i); else if (_e.fd_type[i] == FD_CLIENT) client_read(i); } } }
gboolean client_in_event(G_GNUC_UNUSED GIOChannel *source, GIOCondition condition, gpointer data) { struct client *client = data; enum command_return ret; assert(!client_is_expired(client)); if (condition != G_IO_IN) { client_set_expired(client); return false; } g_timer_start(client->last_activity); ret = client_read(client); switch (ret) { case COMMAND_RETURN_OK: case COMMAND_RETURN_ERROR: break; case COMMAND_RETURN_KILL: client_close(client); //g_main_loop_quit(main_loop); return false; case COMMAND_RETURN_CLOSE: client_close(client); return false; } if (client_is_expired(client)) { client_close(client); return false; } if (!g_queue_is_empty(client->deferred_send)) { /* deferred buffers exist: schedule write */ client->source_id = g_io_add_watch(client->channel, G_IO_OUT|G_IO_ERR|G_IO_HUP, client_out_event, client); return false; } /* read more */ return true; }
static t_res isset_fd_list(void *data_list, void *data) { t_client *client; t_select *select; client = data_list; select = data; if (client->status == OUT) return (R_CONTINUE); if (FD_ISSET(client->socket, &(select->fd_read))) { if (client->type == SERVER) server_read(select, client); else client_read(select, client); } if (FD_ISSET(client->socket, &(select->fd_write))) client_write(select, client); return (R_CONTINUE); }
void *reader(void *arg) { struct timeval timeout; while(1) { fd_set fds; int r, nfds; size_t i; FD_ZERO(&fds); for(i = 0; i < fd_client_index_limit; i++) { if(fd_client_index[i]) { FD_SET(i, &fds); nfds = max(nfds, i); } } timeout.tv_sec = 1; timeout.tv_usec = 0; r = select(nfds + 1, &fds, NULL, NULL, &timeout); if(r == -1 && errno == EINTR) continue; if(r == -1) { perror("select()"); exit(EXIT_FAILURE); } for(i = 0; i < fd_client_index_limit; i++) { if(FD_ISSET(i, &fds)) { client_read(fd_client_index[i]); } } sleep(1); } }
StateResult handle_client(void* arg) { Handler* handler = (Handler*) arg; IoResult ior; if (kresult == NULL) { migrate_state(handler, handle_client_cleanup); if (kmgr->enqueue_pevent(handler) < 0) { eout("[%d]: %s failed to enqueue pevent.\n", mypid, __FUNCTION__); return STATE_ERROR; } dout(2, "[%d]: %s done.\n", mypid, __FUNCTION__); return STATE_OKAY; } switch (kresult->filter) { case EVFILT_READ: dout(2, "[%d]: %s got EVFILT_READ...\n", mypid, __FUNCTION__); ior = client_read(handler); break; case EVFILT_WRITE: dout(2, "[%d]: %s got EVFILT_WRITE...\n", mypid, __FUNCTION__); ior = client_write(handler); break; default: dout(2, "[%d]: %s got unknown filter (%d); closing up shop.\n", mypid, __FUNCTION__, kresult->filter); ior = IO_ERROR; } if (ior < 0) { dout(2, "[%d]: %s got ior %d; close socket.\n", mypid, __FUNCTION__, ior); close(handler->fd); migrate_state(handler, handle_client_cleanup); } dout(2, "[%d]: %s done.\n", mypid, __FUNCTION__); return STATE_OKAY; }
int client_message_auth(Client *client){ int pos = client_read(client, '\n'); if (pos == -1) { error("Socket closed"); } // add extra char for null terminator char data[pos+1]; memset(data, 0, sizeof(data)); strncpy(data, client->buf, pos); if (sizeof(data) > 5) { if (data[0] == 'A' && data[1] == 'U' && data[2] == 'T' && data[3] == 'H' && data[4] == '\t') { char out[sizeof(client->session_id) + 1 + sizeof(data) + 1]; snprintf(out, sizeof(out), "%s\t%s\n", client->session_id, data); client_write_log(client, out); return 0; } } return -1; }
/*** ZE CLIENT ***/ void shell(void){ char buffer[MAX_SIZE]; message_t msg; while(1){ memset(&buffer, '\0', sizeof(buffer) + 1); memset(&msg, 0, sizeof(message_t)); printf("%s", PROMPT); fgets(buffer, sizeof(buffer), stdin); printf("DEBUG: %s\n", buffer); /* Message Decipher */ if(0 == strncmp(buffer, CMD_ADD, strlen(CMD_ADD))){ client_add(buffer); continue; }else if(0 == strncmp(buffer, CMD_INBOX, strlen(CMD_INBOX))){ client_inbox(buffer); continue; }else if(0 == strncmp(buffer, CMD_READ, strlen(CMD_READ))){ client_read(buffer); continue; }else if(0 == strncmp(buffer, CMD_SEND, strlen(CMD_SEND))){ client_send(buffer); continue; }else if(0 == strncmp(buffer, CMD_LIST, strlen(CMD_LIST))){ client_list(buffer); continue; }else if(0 == strncmp(buffer, CMD_ISA, strlen(CMD_ISA))){ client_isa(buffer); continue; } } }
void client_receive(t_socket *socket, t_client *client) { struct s_buffer bf; (void) socket; memset(&bf, 0, sizeof(struct s_buffer)); bf.read = bf.pos = BUFFER_SIZE; while (bf.index <= BUFFER_SIZE) { if (bf.read <= bf.pos) if (!client_read(client, &bf)) return; if (bf.buffer[bf.pos] == '\n') { if (bf.index == 0) return; bf.command[bf.index] = '\0'; (*client->exec)(client, bf.command); bf.index = 0; } else bf.command[bf.index++] = bf.buffer[bf.pos++]; } }
int main(int argc,char** argv) { if (argc != 3) { fprintf(stderr,"usage: RE216_CLIENT hostname port\n"); return 1; } // ----------------------------------------------------------------- // ------------------------ Variables ------------------------------ // Buffer char *input = NULL; // Taille d'entrée dynamique char output[TAILLE_MSG];// Taille de réception fixée // Liste chaînée pour l'envoi de fichiers struct file fichiers; memset(&fichiers, 0, sizeof(struct file)); // Récupération de la structure sockaddr_in6 pour l'adresse du serveur struct sockaddr_in6* server_add = get_addr_info(atoi(argv[2]), argv[1]); // Création de la socket int sckt = do_socket(); // Connexion de la socket à l'adresse server_add int conn = do_connect(sckt, *server_add); // Initialisation des tableaux pour utliser select ------------------ fd_set fd_set_read; // Ici seront stockés les descripteurs de fichier int i, select_ret_val; // Socket du serveur quand elle existe int socket_fichier = -1; // Eventuellement : timeout du select //~ struct timeval tv; //~ tv.tv_sec = 5; //~ tv.tv_usec = 0; init_reg(); // ----------------------------------------------------------------- // ----------------------------------------------------------------- start_line(); // Boucle jusqu'à recevoir le "/quit" final do { // ------------------------ R.A.Z ------------------------------ // clean the set before adding file descriptors FD_ZERO(&fd_set_read); // add the fd for server connection FD_SET(sckt, &fd_set_read); // add the fd for user-input FD_SET(fileno(stdin), &fd_set_read); // ------------------------------------------------------------- // we now wait for any file descriptor to be available for reading select_ret_val = select(sckt + 1, &fd_set_read, NULL, NULL, NULL);//&tv); if (select_ret_val == -1) { error("Erreur concernant le select "); } //printf("Le retour de la fonction select est : %i", select_ret_val); for (i = 0; i < (sckt+1) && select_ret_val > 0; i++) { // Le buffer est nettoyé avec memset directement dans les fonctions //printf("Bonjour je suis le i n°%i. Retour => %i\n", i, select_ret_val); // Si le file descripteur i est dans le set mis en écoute, c'est qu'il y a une activité if (FD_ISSET(i, &fd_set_read)) { // printf("Descripteur trouvé : %i\n", i); if (i == fileno(stdin)) // C'est une entrée utilisateur client_write(&input, sckt, &fichiers); else // Les données viennent du serveur if (!client_read(sckt, output, &fichiers, &socket_fichier)) break; // Select_ret_val est le nombre de descripteurs où il y // a eu une activité, on diminue donc sa valeur au fur // et à mesure. select_ret_val--; } } } while(notquit(input) && notquit(output)); //printf("Extinction.\n"); free(input); free_file(&fichiers); free_reg(); // Fermeture de la socket close_socket(sckt); printf("Fin du tchat\n"); return 0; }
int main(int argc, char** argv){ int sock = 0; // declaración del socket e inicializado a 0 int error = 0; /** declaramos una variable que nos servirá para detectar * errores */ int serverTalk = 0; //socklen_t length = (socklen_t) sizeof (struct sockaddr_in); // tamaño del paquete //struct sockaddr_in addr; // definimos el contenedor de la dirección unsigned int port = 5678; /** creamos la variable que identifica el puerto * de conexión, siendo el puerto por defecto 5678 */ char dir[DIM] = "localhost"; /** definimos la cadena que contendrá a la * dirección del servidor, la cual, será por * defecto localhost */ //struct hostent* server; // estructura utilizada para la gestión de direcciones sms auxMsj; char name[DIM] = {0}; int nbytes = 0; // contador de bytes leidos y escritos char aux[DIM] = {0}; // inicializamos las variables de SSL BIO* bio = NULL; SSL_CTX* ctx = NULL; SSL* ssl = NULL; char cert[DIM] = "/usr/share/doc/libssl-dev/demos/sign/cert.pem"; //analizamos los parámetros de entrada int i = 0; for(; i < argc; i++){ if(strcmp(argv[i], "-p") == 0){ // leemos el puerto if(argc <= i + 1 || isNum(argv[i+1]) == 0){ perror("Se esperaba un número después de -p"); exit(-1); }else{ PDEBUG("INFO: Puerto identificado\n"); i++; port = atoi(argv[i]); } continue; }else if(strcmp(argv[i], "-d") == 0){ // dirección de destino if(argc <= i + 1){ perror("Se esperaba una dirección después de -d"); exit(-1); }else{ PDEBUG("INFO: Destino identificado"); i++; strcpy(dir, argv[i]); } continue; }else if(strcmp(argv[i], "-cert") == 0){ // dirección de destino if(argc <= i + 1){ perror("Se esperaba una ruta de certificado después de -cert"); exit(-1); }else{ PDEBUG("INFO: Destino identificado"); i++; strcpy(cert, argv[i]); } continue; } } /***********************************SSL************************************/ PDEBUG("INFO: Iniciamos la librería SSL\n"); SSL_load_error_strings(); // strings de error SSL_library_init(); // iniciams la libreria en sí ERR_load_BIO_strings(); // strings de error de BIO OpenSSL_add_all_algorithms(); // inicializamos los algoritmos de la librería PDEBUG("INFO: Conectando...\n"); PDEBUG("INFO: Inicializando los punteros\n"); ctx = SSL_CTX_new(SSLv23_client_method()); ssl = NULL; PDEBUG("INFO: Cargamos el certificado\n"); if(SSL_CTX_load_verify_locations(ctx, cert, NULL) == 0){ char aux[] = "ERROR: No se pudo comprobar el certificado\n"; write(WRITE, aux, strlen(aux)); exit(-1); } PDEBUG("INFO: Inicializando BIO\n"); bio = BIO_new_ssl_connect(ctx); BIO_get_ssl(bio, &ssl); if(ssl == 0){ char aux[] = "ERROR: Error al crear el objeto ssl\n"; write(WRITE, aux, strlen(aux)); exit(-1); } PDEBUG("INFO: Estableciendo el modo de trabajo, no queremos reintentos\n"); SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); PDEBUG("INFO: Intentando realizar la conexión\n"); PDEBUG("INFO: Conectando a -> "); sprintf(aux, "%s:%i", dir, port); PDEBUG(aux);PDEBUG("\n"); BIO_set_conn_hostname(bio, aux); PDEBUG("INFO: Verificando la conexión\n"); if (BIO_do_connect(bio) < 1){ char aux[] = "ERROR: al conectar el BIO\n"; write(WRITE, aux, strlen(aux)); exit(-1); } //PDEBUG("INFO: Verificando el resultado de la conexión\n"); //printf("--%i-%i--\n", X509_V_OK, SSL_get_verify_result(ssl)); //if (SSL_get_verify_result(ssl) != X509_V_OK) { // char aux[] = "ERROR: verificar el resultado de la conexión\n"; // write(WRITE, aux, strlen(aux)); // exit(-1); //} PDEBUG("INFO: Conectado\n"); /***********************************SSL************************************/ ////Creamos el socket //PDEBUG("INFO: Creando el socket\n"); //sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); ////Comprobamos si ha ocurrido un error al crear el socket //if(sock < 0){ // char aux[] = "ERROR: creación del socket {{socket()}}:\n"; // write(WRITE, aux, strlen(aux)); // exit(-1); //} // // //addr.sin_family = AF_INET; // familia AF_INET //addr.sin_port = htons(port); // definimos el puerto de conexión //PDEBUG("INFO: Traducimos la dirección del servidor\n"); //server = gethostbyname(dir); /** convertimos la dirección dada // * en una dirección válida para el // * equipo y la metemos en addr // */ ////Comprobamos si ha ocurrido un error obtener el host //if(server == NULL){ // write(WRITE, "ERROR: Host inválido\n", DIM); // // terminamos la ejecución del programa // exit(-1); //} //// copiamos el contenido correspondiente a la dirección de server en addr //bcopy(server->h_addr, &(addr.sin_addr.s_addr), server->h_length); // //// realizamos la conexión al servidor //PDEBUG("INFO: Nos conectamos al servidor\n"); //error = connect(sock, (struct sockaddr*) &addr, length); //if(error < 0){ // char aux[] = "ERROR: al establecer la conexion con el servidor {{connect()}}: \n"; // write(WRITE, aux, strlen(aux)); // // terminamos la ejecución del programa // exit(-1); //} // //PDEBUG("INFO: Conexión establecida\n"); PDEBUG("INFO: Esperando mensaje de bienvenida\n"); memset(&auxMsj, 0, sizeof(sms)); if(client_read(bio, &auxMsj, sizeof(sms)) <= 0){ PDEBUG("INFO: El socket está cerrado\n"); perror("Error al leer contenido del socket porque está cerrado\n"); perror("El cliente se parará\n"); exit(-1); } // atendemos la autentificación del cliente do{ bzero(aux, DIM); sprintf(aux, "%s ~$> %s\n", auxMsj.name, auxMsj.text); write(WRITE, aux, DIM); bzero(&auxMsj.text, SMS_LEN); if(auxMsj.flag == MSJ){ // si es un mensaje, solo imprimimos por la salida estandar memset(&auxMsj, 0, sizeof(sms)); if(client_read(bio, &auxMsj, sizeof(sms)) <= 0){ PDEBUG("INFO: El socket está cerrado\n"); perror("Error al leer contenido del socket porque está cerrado\n"); perror("El cliente se parará\n"); exit(-1); } continue; } if(auxMsj.flag == REQ_PASS){ // si es password desactivamos el echo echo_off(); } nbytes = read(READ, &auxMsj.text, SMS_LEN); if(auxMsj.flag == REQ_PASS){// si es password activamos el echo echo_on(); } auxMsj.text[nbytes - 1] = '\0'; // eliminamos el retorno de carro // nos salimos? if(strcmp(auxMsj.text, "-x") == 0){ PDEBUG("EXIT: Cerrando el cliente, avisando al servidor...\n"); auxMsj.flag = CLI_EXIT; client_write(bio, &auxMsj, sizeof(sms)); PDEBUG("EXIT: Cerrando el socket\n"); shutdown(sock, 2); PDEBUG("EXIT: Cerrando el cliente\n"); exit(0); }else{ // es un mensaje strcpy(name, auxMsj.text); // hacemos una copia del nombre introducido para no perderlo if(auxMsj.flag == REQ_TEXT){ auxMsj.flag = REQ_AUTH; }else if(auxMsj.flag == REQ_PASS){ // entonces REQ_PASS auxMsj.flag = CHECK_PASS; }else if(auxMsj.flag == REQ_ROOM){ // entonces REQ_ROOM auxMsj.flag = CHECK_ROOM; } client_write(bio, &auxMsj, sizeof(sms)); memset(&auxMsj, 0, sizeof(sms)); if(client_read(bio, &auxMsj, sizeof(sms)) <= 0){ PDEBUG("INFO: El socket está cerrado\n"); perror("Error al leer contenido del socket porque está cerrado\n"); perror("El cliente se parará\n"); exit(-1); } } }while(auxMsj.flag != OK); PDEBUG("INFO: Usuario conectado\n"); printf("Usuario conectado...\n"); fd_set desc, descCopy; // definimos un descriptor que contendrá nuestros descriptores //inicializamos la lista de conexiones FD_ZERO(&desc); // Inicio del bit descriptor sock con el valor de sock int fd; if(BIO_get_fd(bio, &fd) < 0){ write(WRITE, "ERROR: crear le descriptor %s\n", DIM); // terminamos la ejecución del programa exit(-1); } FD_SET (fd, &desc); // Inicio del bit descriptor connList con el valor del descriptor de entrada estándar FD_SET (READ, &desc); while(1){ // hacemos una copia de seguridad para asegurarnos de no perder los datos descCopy = desc; // ¿Hay algún socket listo para leer? PDEBUG("INFO: ¿Hay algún socket listo para leer?\n"); error = select(fd + 1, &descCopy, NULL, NULL, NULL); //Comprobamos si ha ocurrido un error al ponernos a escuchar if(error < 0){ write(WRITE, "ERROR: al realizar la selección {{select()}}: %s\n", DIM); // terminamos la ejecución del programa exit(-1); } // recorriendo los sockets para ver los que están activos PDEBUG("INFO: recorriendo los sockets para ver los que están activos\n"); if(FD_ISSET(fd, &descCopy)){ PDEBUG("INFO: Nuevo mensaje recibido\n"); if(client_read(bio, &auxMsj, sizeof(sms)) <= 0){ PDEBUG("INFO: El socket está cerrado\n"); perror("Error al leer contenido del socket porque está cerrado\n"); perror("El cliente se parará\n"); exit(-1); } switch(auxMsj.flag){ case OK: // mensaje de aceptacion, mismo comportamiento que msj case MSJ: // mensaje recibido if(serverTalk != 1 || strcmp(auxMsj.name, SERVER) == 0){ PDEBUG("INFO: Recibido mensaje\n"); sprintf(aux, "%s ~$> %s\n", auxMsj.name, auxMsj.text); write(WRITE, aux, strlen(aux)); sync(); } break; case SERV_EXIT: // el servidor se va a cerrar PDEBUG("EXIT: El servidor se está cerrando, se dejará de leer\n"); shutdown(sock, SHUT_RDWR); sprintf(aux, "%s ~$> Servidor desconectado\n", SERVER); write(WRITE, aux, strlen(aux)); sprintf(aux, "El proceso cliente se cerrará\n"); write(WRITE, aux, strlen(aux)); exit(0); break; default: sprintf(aux, "Recibido un mensaje mal formado\n"); write(WRITE, aux, strlen(aux)); sync(); break; } }else if(FD_ISSET(READ, &descCopy)){ PDEBUG("INFO: Nuevo mensaje escrito\n"); bzero(&auxMsj.text, SMS_LEN); // inicializamos el array nbytes = read(READ, &auxMsj.text, SMS_LEN); // leemos de la entrada estándar auxMsj.text[nbytes - 1] = 0; // eliminamos el retorno de carro // nos salimos? if(strcmp(auxMsj.text, "-x") == 0 && serverTalk != 1){ PDEBUG("EXIT: Cerrando el cliente, avisando al servidor...\n"); auxMsj.flag = CLI_EXIT; }else if(strcmp(auxMsj.text, "--serv") == 0){ // queremos hablar con el servidor PDEBUG("SERV_ADMIN: Iniciando la comunicación directa con el servidor\n"); sprintf(aux, "%s ~$> Iniciada conversación con el servidor\n", SERVER); write(WRITE, aux, strlen(aux)); serverTalk = 1; continue; }else if(sscanf(auxMsj.text, "--mp %s", aux) == 1){ // queremos hablar con el servidor PDEBUG("MP: Mensaje privado detectado\n"); strcpy(auxMsj.to, aux); sprintf(aux, "%s ~$> Inserte el mensaje privado\n", SERVER); write(WRITE, aux, strlen(aux)); auxMsj.flag = MP; nbytes = read(READ, &auxMsj.text, SMS_LEN); // leemos de la entrada estándar auxMsj.text[nbytes - 1] = 0; // eliminamos el retorno de carro }else{ // es un mensaje if(serverTalk == 1){ PDEBUG("SERV_ADMIN: Enviando mensaje al servidor\n"); auxMsj.flag = SERV_ADMIN; if(strcmp(auxMsj.text, "exit") == 0){ serverTalk = 0; sprintf(aux, "%s ~$> Envio de mensajes de configuración terminada:\n", SERVER); write(WRITE, aux, strlen(aux)); continue; } }else{ auxMsj.flag = MSJ; } } strcpy(auxMsj.name, name); // hacemos una copia del nombre introducido para no perderlo PDEBUG("INFO: Enviando mensaje...\n"); client_write(bio, &auxMsj, sizeof(sms)); PDEBUG("INFO: Mensaje Enviado\n"); // nos salimos? if(auxMsj.flag == CLI_EXIT){ PDEBUG("EXIT: Cerrando el socket\n"); shutdown(sock, SHUT_RDWR); PDEBUG("EXIT: Cerrando el cliente\n"); exit(0); } } } return 0; }
RADCLIENT_LIST *client_list_parse_section(CONF_SECTION *section, UNUSED bool tls_required) #endif { bool global = false, in_server = false; CONF_SECTION *cs; RADCLIENT *c; RADCLIENT_LIST *clients; /* * Be forgiving. If there's already a clients, return * it. Otherwise create a new one. */ clients = cf_data_find(section, "clients"); if (clients) return clients; clients = client_list_init(section); if (!clients) return NULL; if (cf_top_section(section) == section) global = true; if (strcmp("server", cf_section_name1(section)) == 0) in_server = true; /* * Associate the clients structure with the section. */ if (cf_data_add(section, "clients", clients, NULL) < 0) { cf_log_err_cs(section, "Failed to associate clients with section %s", cf_section_name1(section)); client_list_free(clients); return NULL; } for (cs = cf_subsection_find_next(section, NULL, "client"); cs != NULL; cs = cf_subsection_find_next(section, cs, "client")) { c = client_afrom_cs(cs, cs, in_server, false); if (!c) { return NULL; } #ifdef WITH_TLS /* * TLS clients CANNOT use non-TLS listeners. * non-TLS clients CANNOT use TLS listeners. */ if (tls_required != c->tls_required) { cf_log_err_cs(cs, "Client does not have the same TLS configuration as the listener"); client_free(c); client_list_free(clients); return NULL; } #endif /* * FIXME: Add the client as data via cf_data_add, * for migration issues. */ #ifdef WITH_DYNAMIC_CLIENTS #ifdef HAVE_DIRENT_H if (c->client_server) { char const *value; CONF_PAIR *cp; DIR *dir; struct dirent *dp; struct stat stat_buf; char buf2[2048]; /* * Find the directory where individual * client definitions are stored. */ cp = cf_pair_find(cs, "directory"); if (!cp) goto add_client; value = cf_pair_value(cp); if (!value) { cf_log_err_cs(cs, "The \"directory\" entry must not be empty"); client_free(c); return NULL; } DEBUG("including dynamic clients in %s", value); dir = opendir(value); if (!dir) { cf_log_err_cs(cs, "Error reading directory %s: %s", value, fr_syserror(errno)); client_free(c); return NULL; } /* * Read the directory, ignoring "." files. */ while ((dp = readdir(dir)) != NULL) { char const *p; RADCLIENT *dc; if (dp->d_name[0] == '.') continue; /* * Check for valid characters */ for (p = dp->d_name; *p != '\0'; p++) { if (isalpha((int)*p) || isdigit((int)*p) || (*p == ':') || (*p == '.')) continue; break; } if (*p != '\0') continue; snprintf(buf2, sizeof(buf2), "%s/%s", value, dp->d_name); if ((stat(buf2, &stat_buf) != 0) || S_ISDIR(stat_buf.st_mode)) continue; dc = client_read(buf2, in_server, true); if (!dc) { cf_log_err_cs(cs, "Failed reading client file \"%s\"", buf2); client_free(c); closedir(dir); return NULL; } /* * Validate, and add to the list. */ if (!client_add_dynamic(clients, c, dc)) { client_free(c); closedir(dir); return NULL; } } /* loop over the directory */ closedir(dir); } #endif /* HAVE_DIRENT_H */ add_client: #endif /* WITH_DYNAMIC_CLIENTS */ if (!client_add(clients, c)) { cf_log_err_cs(cs, "Failed to add client %s", cf_section_name2(cs)); client_free(c); return NULL; } } /* * Replace the global list of clients with the new one. * The old one is still referenced from the original * configuration, and will be freed when that is freed. */ if (global) { root_clients = clients; } return clients; }
/* // Name: main // In: argv, the arguments sent to the program. // argc, the number of arguments sent to the program. */ int main (int argc, char **argv) { char port[6]; char ssl_port[6]; if(!arguments(argv, argc, port, ssl_port)) { printf("Usage: chat_server [port] [ssl port]\n"); return 0; } char topic[MAXTOKENSIZE]; memset(topic, '\0', MAXTOKENSIZE); // Set the signal handler. signal(SIGINT, signal_handler); server_socket = -1; ssl_socket = -1; server_socket_fd; int epoll_fd; struct epoll_event event, ssl_event; BIO *sbio; SSL *ssl; // Initialize ssl context. ctx=init_ctx(); memset(&event, 0, sizeof event); memset(&ssl_event, 0, sizeof event); printf("Trying to create socket.\n"); server_socket_fd = create_socket("telnet", port); ssl_socket_fd = create_socket("telnet", ssl_port); printf("Created socket.\n"); // Check if sockets couldn't be created. if(server_socket_fd<0 || ssl_socket_fd<0) { fprintf(stderr, "Socket could not be created!\n"); return -1; } // Set the socket to be non-blocking. server_socket = unblock_socket(server_socket_fd); ssl_socket = unblock_socket(ssl_socket_fd); if(server_socket<0 || ssl_socket<0) { fprintf(stderr, "Could not make socket non blocking.\n"); return -1; } printf("Listening...\n"); // Listen for incoming connections. server_socket = listen(server_socket_fd, NUMBER_PENDING_CONNECTIONS); ssl_socket = listen(ssl_socket_fd, NUMBER_PENDING_CONNECTIONS); if(server_socket < 0 || ssl_socket<0) { fprintf(stderr, "Could not listen to incoming connections.\n"); return -1; } epoll_fd = epoll_create1(0); event.data.fd = server_socket_fd; // Run as edge-triggered, meaning that epoll_wait will return only on // new events. event.events = EPOLLIN | EPOLLET; // Create epoll control interface for the unsecure socket. server_socket = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_socket_fd, &event); ssl_event.data.fd=ssl_socket_fd; ssl_event.events = EPOLLIN | EPOLLET; // Create epoll control interface for the secure socket. ssl_socket = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, ssl_socket_fd, &ssl_event); if(server_socket<0 || ssl_socket<0) { fprintf(stderr, "Could not create control interface for polling.\n"); return -1; } events = calloc(MAXEVENTS, sizeof event); // Create hash map for storing connected clients. clients = hash_empty(MAXCLIENTS); struct sockaddr client_addr; socklen_t client_len; int insocket_fd; int client_socket; char host[MAXHOST_LEN], serv[MAXSERV_LEN]; client_len = sizeof client_addr; // Main loop listening from events generated by epoll. while(1) { int n,i; // Wait for new events. n = epoll_wait(epoll_fd, events, MAXEVENTS, -1); for(i=0;i<n;i++) { if((events[i].events & EPOLLERR) || events[i].events & EPOLLHUP || (!(events[i].events & EPOLLIN))) { fprintf(stderr, "An error occured at an event.\n"); clientconn_t *c; // If the an error-event occured at a connected client. if((c = hash_get(events[i].data.fd, clients))!=NULL) { client_close(c); hash_remove(c, clients); } close(events[i].data.fd); continue; } // If an a connection is made on the unsecure socket. else if(server_socket_fd == events[i].data.fd) { while(1) { // Accept connection. insocket_fd = accept(server_socket_fd, &client_addr, &client_len); if(insocket_fd<0) { if(!(errno == EAGAIN || errno == EWOULDBLOCK)) { fprintf(stderr, "Could not accept " "input connection"); break; } else { // If the whole handshake could not be made, // keep trying to accept. break; } } // The address information. server_socket = getnameinfo(&client_addr, client_len, host, sizeof host, serv, sizeof serv, NI_NUMERICHOST|NI_NUMERICSERV); if(server_socket==0) { printf("Connection accepted!\n"); } // Make client socket non-blocking. server_socket = unblock_socket(insocket_fd); if(server_socket <0) { fprintf(stderr, "Could not make client socket " "non-blocking\n"); return -1; } // Create an epoll interface for the client socket. event.data.fd = insocket_fd; event.events = EPOLLIN|EPOLLET; server_socket = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, insocket_fd, &event); if(server_socket<0) { fprintf(stderr, "Could not create epoll " "interface for client\n"); return -1; } printf("Added client(%d)!\n", insocket_fd); // Store client in the hash map. c = create_client(insocket_fd, &client_addr); hash_insert(c, clients); } continue; } // If a connection is made on the secure socket. else if(ssl_socket_fd == events[i].data.fd) { printf("Someone connected through ssl!\n"); while(1) { // Accept in the same way as the unsecure socket. insocket_fd = accept(ssl_socket_fd, &client_addr, &client_len); if(insocket_fd<0) { if(!(errno == EAGAIN || errno == EWOULDBLOCK)) { fprintf(stderr, "Could not accept input " "connection\n"); break; } else { break; } } ssl_socket = getnameinfo(&client_addr, client_len, host, sizeof host, serv, sizeof serv, NI_NUMERICHOST|NI_NUMERICSERV); if(ssl_socket==0) { printf("Connection accepted!\n"); } // Make socket non-blocking ssl_socket = unblock_socket(insocket_fd); if(ssl_socket<0){ fprintf(stderr, "Could not make secure client " "socket non-blocking.\n"); return -1; } // Create epoll interface for the secure client connection ssl_event.data.fd = insocket_fd; ssl_event.events = EPOLLIN; ssl_socket = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, insocket_fd, &ssl_event); if(ssl_socket<0) { fprintf(stderr, "Could not create " "epoll interface for client.\n"); return -1; } printf("Added client!(%d)\n", insocket_fd); c = create_client(insocket_fd, &client_addr); // Set up ssl. c->ssl_status=STATUS_HANDSHAKE; c->ssl = SSL_new(ctx); SSL_set_fd(c->ssl, insocket_fd); SSL_set_mode(c->ssl, SSL_MODE_ENABLE_PARTIAL_WRITE); hash_insert(c, clients); } continue; } // If an incoming message has caused an event. else { int done = 0; while (1) { ssize_t count; char buf[MAXBUFSIZE]; memset(buf, '\0', MAXBUFSIZE); clientconn_t *c = hash_get(events[i].data.fd, clients); // If the client is trying to make an ssl handshake. if(c->ssl_status==STATUS_HANDSHAKE) { int r=1; r=SSL_accept(c->ssl); if (r<0) { if(SSL_get_error(c->ssl, r)!=SSL_ERROR_WANT_READ && SSL_get_error(c->ssl, r)!=SSL_ERROR_WANT_WRITE ){ done=1; printf("Could not accept ssl " "connection\n"); break; } } else { // Handshake is done. c->ssl_status=STATUS_ACCEPTED; } } else { // Read data from client. int count = client_read(c, buf, sizeof buf); if(count<0) { if(errno!=EAGAIN) { fprintf(stderr, "Could not read" " from socket!\n"); done=1; } break; } if(buf[MAXBUFSIZE-1] != '\0') { write(events[i].data.fd, "* BAD Buffer will " "overflow\r\n", 28); break; } else if (count==0) { done=1; break; } if (handle_input(events[i].data.fd, buf, count, clients, topic)==CLIENTCLOSED) { done=1; break; } if(server_socket<0) { fprintf(stderr, "Could get input.\n"); return -1; } } } // Client connection is done, wants to disconnect. if(done) { printf("Closed connection!\n"); clientconn_t *closeclient = hash_get(events[i].data.fd, clients); if(closeclient != NULL) { hash_remove(closeclient, clients); client_close(closeclient); } close(events[i].data.fd); } } } } free(events); close(server_socket_fd); return 0; }
/* * Replicates a given file * Takes the index in the server table for from and to * Caller must lock the global tables (modifies the file_list) */ int replicate(int f_idx, int from, int to) { char *f_name = file_list[f_idx].name; char *s_from = server_list[from].name; char *s_to = server_list[to].name; int fd_from = -1; int fd_to = -1; int sock_from = -1; int sock_to = -1; int r_len = -1, w_len = -1; char buff[8192]; // See if src is same as destn if (from == to) { printf ("***NO REPLICATE*** from == to\n"); return(-1);; } // connect to servers if (((sock_from = connect_to_server(s_from, server_port)) < 0 ) || ((sock_to = connect_to_server(s_to, server_port)) < 0 )) { perror("Replication failed"); if (sock_from >= 0) close(sock_from); if (sock_to >= 0) close(sock_to); return(-1); } // open files if (((fd_from = client_open(sock_from, f_name, O_RDONLY)) < 0 ) || ((fd_to = client_open(sock_to, f_name, O_CREAT | O_WRONLY)) < 0 )) { perror("Replication failed"); if (fd_from >= 0) client_close(sock_from, fd_from); client_end(sock_from); if(fd_to >= 0) client_close(sock_to, fd_to); client_end(sock_to); return(-2); } // read file from source server and transfer to dest server do { if ((r_len = client_read(sock_from, fd_from, buff, sizeof(buff))) < 0) { perror("Replication failed"); client_close(sock_from, fd_from); client_end(sock_from); client_close(sock_to, fd_to); client_end(sock_to); return(-3); } if ((w_len = client_write(sock_to, fd_to, buff, r_len)) < 0 ) { perror("Replication failed"); client_close(sock_from, fd_from); client_end(sock_from); client_close(sock_to, fd_to); client_end(sock_to); return(-4); } } while (r_len == sizeof(buff)); // read until eof // close files client_close(sock_from, fd_from); client_end(sock_from); client_close(sock_to, fd_to); client_end(sock_to); // update tables - add destn server to file's record file_list[f_idx].index[file_list[f_idx].tot_idx++] = to; return(0); }
int main(int argc, char **argv) { int status, i, listener; time_t tardy; char *port, *p; extern char *database; struct stat stbuf; struct utsname uts; fd_set readfds, writefds, xreadfds, xwritefds; int nfds, counter = 0; whoami = argv[0]; /* * Error handler init. */ mr_init(); set_com_err_hook(mr_com_err); setvbuf(stderr, NULL, _IOLBF, BUFSIZ); port = strchr(MOIRA_SERVER, ':') + 1; for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-db") && i + 1 < argc) { database = argv[i + 1]; i++; } else if (!strcmp(argv[i], "-p") && i + 1 < argc) { port = argv[i + 1]; i++; } else { com_err(whoami, 0, "Usage: moirad [-db database][-p port]"); exit(1); } } status = krb5_init_context(&context); if (status) { com_err(whoami, status, "Initializing krb5 context."); exit(1); } status = krb5_get_default_realm(context, &krb_realm); if (status) { com_err(whoami, status, "Getting default Kerberos realm."); exit(1); } /* * Database initialization. Only init if database should be open. */ if (stat(MOIRA_MOTD_FILE, &stbuf) != 0) { if ((status = mr_open_database())) { com_err(whoami, status, "trying to open database."); exit(1); } sanity_check_database(); } else { dormant = ASLEEP; com_err(whoami, 0, "sleeping, not opening database"); } sanity_check_queries(); /* * Get moira server hostname for authentication */ if (uname(&uts) < 0) { com_err(whoami, errno, "Unable to get local hostname"); exit(1); } host = canonicalize_hostname(xstrdup(uts.nodename)); for (p = host; *p && *p != '.'; p++) { if (isupper(*p)) *p = tolower(*p); } *p = '\0'; /* * Set up client array handler. */ nclients = 0; clientssize = 10; clients = xmalloc(clientssize * sizeof(client *)); mr_setup_signals(); journal = fopen(JOURNAL, "a"); if (!journal) { com_err(whoami, errno, "opening journal file"); exit(1); } /* * Establish template connection. */ listener = mr_listen(port); if (listener == -1) { com_err(whoami, MR_ABORTED, "trying to create listening connection"); exit(1); } FD_ZERO(&xreadfds); FD_ZERO(&xwritefds); FD_SET(listener, &xreadfds); nfds = listener + 1; com_err(whoami, 0, "started (pid %d)", getpid()); com_err(whoami, 0, rcsid); if (dormant != ASLEEP) send_zgram("MOIRA", "server started"); else send_zgram("MOIRA", "server started, but database closed"); /* * Run until shut down. */ while (!takedown) { int i; struct timeval timeout = {60, 0}; /* 1 minute */ /* If we're supposed to go down and we can, do it */ if (((dormant == AWAKE) && (nclients == 0) && (stat(MOIRA_MOTD_FILE, &stbuf) == 0)) || (dormant == SLEEPY)) { mr_close_database(); com_err(whoami, 0, "database closed"); mr_setup_signals(); send_zgram("MOIRA", "database closed"); dormant = ASLEEP; } /* Block until something happens. */ memcpy(&readfds, &xreadfds, sizeof(readfds)); memcpy(&writefds, &xwritefds, sizeof(writefds)); if (select(nfds, &readfds, &writefds, NULL, &timeout) == -1) { if (errno != EINTR) com_err(whoami, errno, "in select"); continue; } if (takedown) break; if (child_exited_abnormally) { critical_alert(whoami, "moirad", "%d: child exits with signal %d status %d", child_pid, child_signal, child_status); child_exited_abnormally = 0; } time(&now); tardy = now - 30 * 60; /* If we're asleep and we should wake up, do it */ if ((dormant == ASLEEP) && (stat(MOIRA_MOTD_FILE, &stbuf) == -1) && (errno == ENOENT)) { mr_open_database(); com_err(whoami, 0, "database open"); mr_setup_signals(); send_zgram("MOIRA", "database open again"); dormant = AWAKE; } /* Handle any new connections */ if (FD_ISSET(listener, &readfds)) { int newconn, addrlen = sizeof(struct sockaddr_in); struct sockaddr_in addr; client *cp; newconn = accept(listener, (struct sockaddr *)&addr, &addrlen); if (newconn == -1) com_err(whoami, errno, "accepting new connection"); else if (newconn > 0) { if (newconn + 1 > nfds) nfds = newconn + 1; FD_SET(newconn, &xreadfds); /* Add a new client to the array */ nclients++; if (nclients > clientssize) { clientssize = 2 * clientssize; clients = xrealloc(clients, clientssize * sizeof(client *)); } clients[nclients - 1] = cp = xmalloc(sizeof(client)); memset(cp, 0, sizeof(client)); cp->con = newconn; cp->id = counter++; cp->last_time_used = now; cp->haddr = addr; cp->tuplessize = 1; cp->tuples = xmalloc(sizeof(mr_params)); memset(cp->tuples, 0, sizeof(mr_params)); cp->state = CL_ACCEPTING; cp->version = 2; cur_client = cp; com_err(whoami, 0, "New connection from %s port %d (now %d client%s)", inet_ntoa(cp->haddr.sin_addr), (int)ntohs(cp->haddr.sin_port), nclients, nclients != 1 ? "s" : ""); } } /* Handle any existing connections. */ for (i = 0; i < nclients; i++) { cur_client = clients[i]; if (FD_ISSET(clients[i]->con, &writefds)) { client_write(clients[i]); if (!clients[i]->ntuples) { FD_CLR(clients[i]->con, &xwritefds); FD_SET(clients[i]->con, &xreadfds); } clients[i]->last_time_used = now; } if (FD_ISSET(clients[i]->con, &readfds)) { if (clients[i]->state == CL_ACCEPTING) { switch(mr_cont_accept(clients[i]->con, &clients[i]->hsbuf, &clients[i]->hslen)) { case -1: break; case 0: clients[i]->state = CL_CLOSING; break; default: clients[i]->state = CL_ACTIVE; clients[i]->hsbuf = NULL; break; } } else { client_read(clients[i]); if (clients[i]->ntuples) { FD_CLR(clients[i]->con, &xreadfds); FD_SET(clients[i]->con, &xwritefds); } clients[i]->last_time_used = now; } } if (clients[i]->last_time_used < tardy) { com_err(whoami, 0, "Shutting down connection due to inactivity"); clients[i]->state = CL_CLOSING; } if (clients[i]->state == CL_CLOSING) { client *old; com_err(whoami, 0, "Closed connection (now %d client%s, " "%d queries)", nclients - 1, nclients != 2 ? "s" : "", newqueries); shutdown(clients[i]->con, 2); close(clients[i]->con); FD_CLR(clients[i]->con, &xreadfds); FD_CLR(clients[i]->con, &xwritefds); free_rtn_tuples(clients[i]); free(clients[i]->tuples); if (clients[i]->hsbuf) free(clients[i]->hsbuf); old = clients[i]; clients[i] = clients[--nclients]; free(old); } cur_client = NULL; if (takedown) break; } } com_err(whoami, 0, "%s", takedown); if (dormant != ASLEEP) mr_close_database(); send_zgram("MOIRA", takedown); return 0; }
static void *st_poolThread(void* pArg) { char buf[BUFFER_SIZE]; cJSON *msg = NULL; pthread_cleanup_push(st_poolThreadCleanup, NULL); for(;;) { pthread_testcancel(); if (client_read( &pool.socket, buf, sizeof(buf)) <= 0) { usleep(50000); continue; } RPC_TRACE("st: <- %s\n", buf); msg = cJSON_Parse( buf ); if( !msg ) { eprintf("%s: failed to parse message: '%s'\n", __FUNCTION__, buf); continue; } elcdRpcType_t type = elcdRpcInvalid; cJSON *value = NULL; cJSON *id = cJSON_GetObjectItem(msg, "id"); if( !id || id->type != cJSON_Number || id->valueint == 0 ) { eprintf("%s: missing id\n", __FUNCTION__); goto type_known; } value = cJSON_GetObjectItem( msg, "method" ); if( value != NULL && value->type == cJSON_String ) { type = elcdRpcRequest; goto type_known; } value = cJSON_DetachItemFromObject( msg, "result" ); if( value != NULL && value->type != cJSON_NULL ) { type = elcdRpcResult; goto type_known; } value = cJSON_DetachItemFromObject( msg, "error" ); if( value != NULL && value->type != cJSON_NULL ) { type = elcdRpcError; } type_known: dprintf( "%s: <- %s type %d\n", __FUNCTION__, buf, type); switch( type ) { case elcdRpcInvalid: eprintf("%s: malformed message: '%s'\n", __FUNCTION__, buf); break; case elcdRpcRequest: /// TODO eprintf("%s: don't know what to do with request %s\n", __FUNCTION__, value->valuestring); break; case elcdRpcError: case elcdRpcResult: { int i; for( i = 0; i < RPC_POOL_SIZE; i++ ) if( (unsigned int)id->valueint == pool.waiting[i].id ) { if(pool.waiting[i].callback) { pool.waiting[i].callback( type, value, pool.waiting[i].pArg ); } st_poolFreeAt(i); break; } if( i >= RPC_POOL_SIZE ) { eprintf("%s: lost message %6u\n", __FUNCTION__, (unsigned int)id->valueint); cJSON_Delete(value); } st_poolPrint(); break; } } cJSON_Delete(msg); msg = NULL; } pthread_cleanup_pop(1); pthread_exit(NULL); }
// handle the websocket handshake void client_read_ws_handshake ( struct bufferevent* be, void* arg ) { // Examine the input buffer without reading from it. // Wait untill we have the full handshake to begin processing. int len = EVBUFFER_LENGTH ( EVBUFFER_INPUT ( be ) ); char* data = EVBUFFER_DATA ( EVBUFFER_INPUT ( be ) ); char buf[1024]; if ( len > sizeof buf ) len = sizeof buf; memcpy ( buf, data, len ); buf[len] = '\0'; // the spec http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-68 is very // strict regarding the handshake. char* endofheaders = strstr ( buf, "\r\n\r\n" ); if ( endofheaders == NULL ) return; char* origin; char* eoo; // end of origin if ( ( origin = strstr ( buf, "Origin:" ) ) == NULL || ( eoo = strchr ( origin, '\r' ) ) == NULL ) { // didn't get all of the websocket headers, read more return; } origin += 8; *eoo = '\0'; // chop the buffer up at each space char char* strings[50]; int n = 0; char* ptmp; char* p = strtok_r ( buf, " ", &ptmp ); while ( n < 50 && p != NULL ) { strings[n++] = p; p = strtok_r ( NULL, " ", &ptmp ); } if ( n < 7 || strncmp ( "GET", strings[0], 3 ) != 0 || strncmp ( "HTTP/1.1\r\nUpgrade:", strings[2], 18 ) != 0 || strncmp ( "WebSocket\r\nConnection:", strings[3], 22 ) != 0 || strncmp ( "Upgrade\r\nHost:", strings[4], 15 ) != 0 || strlen ( strings[5] ) < 9 || strlen ( strings[6] ) < 4 ) { // error } char* host = strings[5]; int l = strlen ( host ); host[l - 9] = '\0'; // grab the info we are interested in host = strdup ( host ); origin = strdup ( origin ); char* uri = strdup ( strings[1] ); // remove the handshake and headers from the input buffer int hs_len = buf - endofheaders + 4; bufferevent_read ( be, buf, hs_len ); // send handshake response snprintf ( buf, sizeof buf, "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" "Upgrade: WebSocket\r\n" "Connection: Upgrade\r\n" "WebSocket-Origin: %s\r\n" "WebSocket-Location: ws://%s%s\r\n\r\n", origin, host, uri ); free ( host ); free ( origin ); free ( uri ); // send websock handshake bufferevent_write ( be, buf, strlen ( buf ) ); bufferevent_enable ( be, EV_WRITE ); struct bufferevent* server = connect_to_server ( serverhost, serverport, be ); // reconfig the read callback bufferevent_setcb ( be, client_read, NULL, be_error, server ); client_read ( be, server ); }