static int _ecore_con_ssl_server_read_openssl(Ecore_Con_Server *svr, unsigned char *buf, int size) { int num; if (!svr->ssl) return -1; num = SSL_read(svr->ssl, buf, size); svr->ssl_err = SSL_get_error(svr->ssl, num); if (svr->fd_handler) { if (svr->ssl && svr->ssl_err == SSL_ERROR_WANT_READ) ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ); else if (svr->ssl && svr->ssl_err == SSL_ERROR_WANT_WRITE) ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE); } if ((svr->ssl_err == SSL_ERROR_ZERO_RETURN) || (svr->ssl_err == SSL_ERROR_SYSCALL) || (svr->ssl_err == SSL_ERROR_SSL)) return -1; if (num < 0) return 0; return num; }
static int _ecore_con_ssl_client_write_openssl(Ecore_Con_Client *cl, unsigned char *buf, int size) { int num; num = SSL_write(cl->ssl, buf, size); cl->ssl_err = SSL_get_error(cl->ssl, num); if (cl->fd_handler) { if (cl->ssl && cl->ssl_err == SSL_ERROR_WANT_READ) ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ); else if (cl->ssl && cl->ssl_err == SSL_ERROR_WANT_WRITE) ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE); } if ((cl->ssl_err == SSL_ERROR_ZERO_RETURN) || (cl->ssl_err == SSL_ERROR_SYSCALL) || (cl->ssl_err == SSL_ERROR_SSL)) return -1; if (num < 0) return 0; return num; }
static Eina_Bool _process_data(gnutls_session_t client, Ecore_Fd_Handler * fd_handler) { static int ret, lastret; static unsigned int count = 0; if (!done) { lastret = ret; ret = gnutls_handshake(client); count++; if (gnutls_record_get_direction(client)) ecore_main_fd_handler_active_set(fd_handler, ECORE_FD_WRITE); else ecore_main_fd_handler_active_set(fd_handler, ECORE_FD_READ); /* avoid printing messages infinity times */ if (lastret != ret && ret != 0 && ret != GNUTLS_E_AGAIN) { print("gnutls returned with: %s - %s", gnutls_strerror_name(ret), gnutls_strerror(ret)); if ((ret == GNUTLS_E_WARNING_ALERT_RECEIVED) || (ret == GNUTLS_E_FATAL_ALERT_RECEIVED)) print("Also received alert: %s", gnutls_alert_get_name (gnutls_alert_get(client))); print("last out: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS (gnutls_handshake_get_last_out(client))); print("last in: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS (gnutls_handshake_get_last_in(client))); } if (gnutls_error_is_fatal(ret)) { print("yarrr this be an error!"); exit(1); } } if (ret == GNUTLS_E_SUCCESS) { done = 1; //print("Handshake successful in %u handshake calls!", count); ecore_main_loop_quit(); } return ECORE_CALLBACK_RENEW; }
Eina_Bool esql_reconnect_handler(Esql *e) { Esql *ev; int ret, fd; ev = e->pool_member ? (Esql *)e->pool_struct : e; /* use pool struct for events */ e->reconnect_timer = NULL; ret = e->backend.connect(e); EINA_SAFETY_ON_NULL_GOTO(e->backend.db, error); if (ret == ECORE_FD_ERROR) { ERR("Connection error: %s", e->backend.error_get(e)); goto error; } fd = e->backend.fd_get(e); if (fd != -1) { e->fdh = ecore_main_fd_handler_add(fd, ECORE_FD_READ | ECORE_FD_WRITE | ECORE_FD_ERROR, (Ecore_Fd_Cb)esql_connect_handler, e, NULL, NULL); ecore_main_fd_handler_active_set(e->fdh, ret); e->current = ESQL_CONNECT_TYPE_INIT; if (ev->database) esql_database_set(e, ev->database); } return EINA_FALSE; error: ecore_event_add(ESQL_EVENT_DISCONNECT, ev, (Ecore_End_Cb)esql_fake_free, NULL); e->event_count++; return EINA_FALSE; }
/** * @brief Connect to an sql server * Use this function to connect to an sql server with @p e after * setting its type with esql_type_set. * @param e The object to connect with (NOT NULL) * @param addr The address of the server (ie "127.0.0.1:3306") (NOT NULL) * @param user The username to connect with (NOT NULL) * @param passwd The password for @p user * @return EINA_TRUE if the connection could be started, else EINA_FALSE */ Eina_Bool esql_connect(Esql *e, const char *addr, const char *user, const char *passwd) { int ret, fd; EINA_SAFETY_ON_NULL_RETURN_VAL(e, EINA_FALSE); EINA_SAFETY_ON_TRUE_RETURN_VAL(e->type == ESQL_TYPE_NONE, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(addr, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(user, EINA_FALSE); if (e->pool) return esql_pool_connect((Esql_Pool *)e, addr, user, passwd); EINA_SAFETY_ON_TRUE_RETURN_VAL(!e->backend.db && (e->type == ESQL_TYPE_MYSQL), EINA_FALSE); if (e->connected) { ERR("Connection error: already connected!"); return EINA_FALSE; } e->backend.setup(e, addr, user, passwd); ret = e->backend.connect(e); EINA_SAFETY_ON_NULL_RETURN_VAL(e->backend.db, EINA_FALSE); if (ret == ECORE_FD_ERROR) { ERR("Connection error: %s", e->backend.error_get(e)); return EINA_FALSE; } fd = e->backend.fd_get(e); e->fdh = ecore_main_fd_handler_add(fd, ECORE_FD_READ | ECORE_FD_WRITE, (Ecore_Fd_Cb)esql_connect_handler, e, NULL, NULL); ecore_main_fd_handler_active_set(e->fdh, ret); e->current = ESQL_CONNECT_TYPE_INIT; return EINA_TRUE; }
static void on_prepare (void *udata, Ecore_Fd_Handler *handler) { xmmsc_connection_t *c = udata; int flags = ECORE_FD_READ | ECORE_FD_ERROR; if (xmmsc_io_want_out (c)) flags |= ECORE_FD_WRITE; ecore_main_fd_handler_active_set (handler, flags); }
Eina_Bool esql_connect_handler(Esql *e, Ecore_Fd_Handler *fdh) { int ret; DBG("(e=%p, fdh=%p, qid=%u)", e, fdh, e->cur_id); if (fdh) ecore_main_fd_handler_active_set(fdh, 0); if (e->pool_member) INFO("Pool member %u: Running io", e->pool_id); else INFO("Running io"); if (e->timeout_timer) ecore_timer_reset(e->timeout_timer); ret = e->backend.io(e); switch (ret) { case 0: esql_call_complete(e); break; case ECORE_FD_READ | ECORE_FD_WRITE: if (fdh) ecore_main_fd_handler_active_set(fdh, ECORE_FD_READ | ECORE_FD_WRITE); break; case ECORE_FD_READ: ecore_main_fd_handler_active_set(fdh, ECORE_FD_READ); break; case ECORE_FD_WRITE: ecore_main_fd_handler_active_set(fdh, ECORE_FD_WRITE); break; default: ERR("Error return from io()"); esql_event_error(e); } return ECORE_CALLBACK_RENEW; }
static void _ecore_pa_io_enable(pa_io_event *event, pa_io_event_flags_t flags) { event->flags = flags; ecore_main_fd_handler_active_set(event->handler, map_flags_to_ecore(flags)); }
static Ecore_Con_Ssl_Error _ecore_con_ssl_client_init_gnutls(Ecore_Con_Client *cl) { const gnutls_datum_t *cert_list; unsigned int iter, cert_list_size; const char *priority = "NONE:%VERIFY_ALLOW_X509_V1_CA_CRT:+RSA:+DHE-RSA:+DHE-DSS:+ANON-DH:+COMP-DEFLATE:+COMP-NULL:+CTYPE-X509:+SHA1:+SHA256:+SHA384:+SHA512:+AES-256-CBC:+AES-128-CBC:+3DES-CBC:+VERS-TLS1.2:+VERS-TLS1.1:+VERS-TLS1.0:+VERS-SSL3.0"; int ret = 0; switch (cl->ssl_state) { case ECORE_CON_SSL_STATE_DONE: return ECORE_CON_SSL_ERROR_NONE; case ECORE_CON_SSL_STATE_INIT: if (cl->host_server->type & ECORE_CON_USE_SSL2) /* not supported because of security issues */ return ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED; switch (cl->host_server->type & ECORE_CON_SSL) { case ECORE_CON_USE_SSL3: case ECORE_CON_USE_SSL3 | ECORE_CON_LOAD_CERT: priority = "NONE:%VERIFY_ALLOW_X509_V1_CA_CRT:+RSA:+DHE-RSA:+DHE-DSS:+ANON-DH:+COMP-DEFLATE:+COMP-NULL:+CTYPE-X509:+SHA1:+SHA256:+SHA384:+SHA512:+AES-256-CBC:+AES-128-CBC:+3DES-CBC:!VERS-TLS1.0:!VERS-TLS1.1"; break; case ECORE_CON_USE_TLS: case ECORE_CON_USE_TLS | ECORE_CON_LOAD_CERT: priority = "NONE:%VERIFY_ALLOW_X509_V1_CA_CRT:+RSA:+DHE-RSA:+DHE-DSS:+ANON-DH:+COMP-DEFLATE:+COMP-NULL:+CTYPE-X509:+SHA1:+SHA256:+SHA384:+SHA512:+AES-256-CBC:+AES-128-CBC:+3DES-CBC:!VERS-SSL3.0"; break; case ECORE_CON_USE_MIXED: case ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT: break; default: return ECORE_CON_SSL_ERROR_NONE; } _client_connected++; SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_init(&cl->session, GNUTLS_SERVER)); SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_session_ticket_key_generate(&cl->session_ticket)); SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_session_ticket_enable_server(cl->session, &cl->session_ticket)); INF("Applying priority string: %s", priority); SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_priority_set_direct(cl->session, priority, NULL)); SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(cl->session, GNUTLS_CRD_CERTIFICATE, cl->host_server->cert)); // SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(cl->session, GNUTLS_CRD_PSK, cl->host_server->pskcred_s)); if (!cl->host_server->use_cert) SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(cl->session, GNUTLS_CRD_ANON, cl->host_server->anoncred_s)); gnutls_certificate_server_set_request(cl->session, GNUTLS_CERT_REQUEST); gnutls_dh_set_prime_bits(cl->session, 2048); gnutls_transport_set_ptr(cl->session, (gnutls_transport_ptr_t)((intptr_t)cl->fd)); cl->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING; case ECORE_CON_SSL_STATE_HANDSHAKING: if (!cl->session) { DBG("Client was previously lost, going to error condition"); goto error; } DBG("calling gnutls_handshake()"); ret = gnutls_handshake(cl->session); SSL_ERROR_CHECK_GOTO_ERROR(gnutls_error_is_fatal(ret)); if (!ret) { cl->handshaking = EINA_FALSE; cl->ssl_state = ECORE_CON_SSL_STATE_DONE; } else { if (gnutls_record_get_direction(cl->session)) ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE); else ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ); return ECORE_CON_SSL_ERROR_NONE; } default: break; } if (!cl->host_server->verify) /* not verifying certificates, so we're done! */ return ECORE_CON_SSL_ERROR_NONE; ret = 0; /* use CRL/CA lists to verify */ SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_certificate_verify_peers2(cl->session, &iter)); if (iter & GNUTLS_CERT_INVALID) ERR("The certificate is not trusted."); else if (iter & GNUTLS_CERT_SIGNER_NOT_FOUND) ERR("The certificate hasn't got a known issuer."); else if (iter & GNUTLS_CERT_REVOKED) ERR("The certificate has been revoked."); else if (iter & GNUTLS_CERT_EXPIRED) ERR("The certificate has expired"); else if (iter & GNUTLS_CERT_NOT_ACTIVATED) ERR("The certificate is not yet activated"); if (iter) goto error; if (gnutls_certificate_type_get(cl->session) != GNUTLS_CRT_X509) { ERR("Warning: PGP certificates are not yet supported!"); goto error; } SSL_ERROR_CHECK_GOTO_ERROR(!(cert_list = gnutls_certificate_get_peers(cl->session, &cert_list_size))); SSL_ERROR_CHECK_GOTO_ERROR(!cert_list_size); DBG("SSL certificate verification succeeded!"); return ECORE_CON_SSL_ERROR_NONE; error: _gnutls_print_errors(ret); if ((ret == GNUTLS_E_WARNING_ALERT_RECEIVED) || (ret == GNUTLS_E_FATAL_ALERT_RECEIVED)) ERR("Also received alert: %s", gnutls_alert_get_name(gnutls_alert_get(cl->session))); if (cl->session && (cl->ssl_state != ECORE_CON_SSL_STATE_DONE)) { ERR("last out: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_get_last_out(cl->session))); ERR("last in: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_get_last_in(cl->session))); } _ecore_con_ssl_client_shutdown_gnutls(cl); return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED; }
static Ecore_Con_Ssl_Error _ecore_con_ssl_client_init_openssl(Ecore_Con_Client *cl) { int ret = -1; switch (cl->ssl_state) { case ECORE_CON_SSL_STATE_DONE: return ECORE_CON_SSL_ERROR_NONE; case ECORE_CON_SSL_STATE_INIT: SSL_ERROR_CHECK_GOTO_ERROR(!(cl->ssl = SSL_new(cl->host_server->ssl_ctx))); SSL_ERROR_CHECK_GOTO_ERROR(!SSL_set_fd(cl->ssl, cl->fd)); SSL_set_accept_state(cl->ssl); cl->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING; case ECORE_CON_SSL_STATE_HANDSHAKING: if (!cl->ssl) { DBG("Client was previously lost, going to error condition"); goto error; } ret = SSL_do_handshake(cl->ssl); cl->ssl_err = SSL_get_error(cl->ssl, ret); SSL_ERROR_CHECK_GOTO_ERROR((cl->ssl_err == SSL_ERROR_SYSCALL) || (cl->ssl_err == SSL_ERROR_SSL)); if (ret == 1) { cl->handshaking = EINA_FALSE; cl->ssl_state = ECORE_CON_SSL_STATE_DONE; } else { if (cl->ssl_err == SSL_ERROR_WANT_READ) ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ); else if (cl->ssl_err == SSL_ERROR_WANT_WRITE) ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE); return ECORE_CON_SSL_ERROR_NONE; } default: break; } #ifdef ISCOMFITOR { /* print session info into DBG */ SSL_SESSION *s; BIO *b; char log[4096]; memset(log, 0, sizeof(log)); s = SSL_get_session(cl->ssl); b = BIO_new(BIO_s_mem()); SSL_SESSION_print(b, s); while (BIO_read(b, log, sizeof(log)) > 0) DBG("%s", log); BIO_free(b); } #endif if (!cl->host_server->verify) /* not verifying certificates, so we're done! */ return ECORE_CON_SSL_ERROR_NONE; SSL_set_verify(cl->ssl, SSL_VERIFY_PEER, NULL); /* use CRL/CA lists to verify */ if (SSL_get_peer_certificate(cl->ssl)) SSL_ERROR_CHECK_GOTO_ERROR(SSL_get_verify_result(cl->ssl)); return ECORE_CON_SSL_ERROR_NONE; error: _openssl_print_errors(); _ecore_con_ssl_client_shutdown_openssl(cl); return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED; }
static Ecore_Con_Ssl_Error _ecore_con_ssl_server_init_openssl(Ecore_Con_Server *svr) { int ret = -1; switch (svr->ssl_state) { case ECORE_CON_SSL_STATE_DONE: return ECORE_CON_SSL_ERROR_NONE; case ECORE_CON_SSL_STATE_INIT: SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl = SSL_new(svr->ssl_ctx))); SSL_ERROR_CHECK_GOTO_ERROR(!SSL_set_fd(svr->ssl, svr->fd)); SSL_set_connect_state(svr->ssl); svr->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING; case ECORE_CON_SSL_STATE_HANDSHAKING: if (!svr->ssl) { DBG("Server was previously lost, going to error condition"); goto error; } ret = SSL_do_handshake(svr->ssl); svr->ssl_err = SSL_get_error(svr->ssl, ret); SSL_ERROR_CHECK_GOTO_ERROR((svr->ssl_err == SSL_ERROR_SYSCALL) || (svr->ssl_err == SSL_ERROR_SSL)); if (ret == 1) { svr->handshaking = EINA_FALSE; svr->ssl_state = ECORE_CON_SSL_STATE_DONE; } else { if (svr->ssl_err == SSL_ERROR_WANT_READ) ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ); else if (svr->ssl_err == SSL_ERROR_WANT_WRITE) ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE); return ECORE_CON_SSL_ERROR_NONE; } default: break; } #ifdef ISCOMFITOR { /* print session info into DBG */ SSL_SESSION *s; BIO *b; char log[4096]; memset(log, 0, sizeof(log)); s = SSL_get_session(svr->ssl); b = BIO_new(BIO_s_mem()); SSL_SESSION_print(b, s); while (BIO_read(b, log, sizeof(log)) > 0) DBG("%s", log); BIO_free(b); } #endif if (!svr->verify) /* not verifying certificates, so we're done! */ return ECORE_CON_SSL_ERROR_NONE; { X509 *cert; SSL_set_verify(svr->ssl, SSL_VERIFY_PEER, NULL); /* use CRL/CA lists to verify */ cert = SSL_get_peer_certificate(svr->ssl); if (cert) { char buf[256] = {0}; SSL_ERROR_CHECK_GOTO_ERROR(SSL_get_verify_result(svr->ssl)); X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_subject_alt_name, buf, sizeof(buf)); if (buf[0]) SSL_ERROR_CHECK_GOTO_ERROR(!_openssl_name_verify(buf, svr->name)); else { X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName, buf, sizeof(buf)); SSL_ERROR_CHECK_GOTO_ERROR(!_openssl_name_verify(buf, svr->name)); } } } DBG("SSL certificate verification succeeded!"); return ECORE_CON_SSL_ERROR_NONE; error: _openssl_print_errors(); _ecore_con_ssl_server_shutdown_openssl(svr); return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED; }
static int _ecore_con_dns_check(Ecore_Con_DNS *dns) { struct addrinfo *ent = NULL; int error = 0; error = dns_ai_nextent(&ent, dns->ai); switch (error) { case 0: break; case EAGAIN: return 1; default: ERR("resolve failed: %s", dns_strerror(error)); goto error; } { Ecore_Con_Info result = {0, .ip = {0}, .service = {0}}; #if 0 char pretty[512]; dns_ai_print(pretty, sizeof(pretty), ent, dns->ai); printf("%s\n", pretty); #endif result.size = 0; dns_inet_ntop(dns_sa_family(ent->ai_addr), dns_sa_addr(dns_sa_family(ent->ai_addr), ent->ai_addr), result.ip, sizeof(result.ip)); snprintf(result.service, sizeof(result.service), "%u", ntohs(*dns_sa_port(dns_sa_family(ent->ai_addr), ent->ai_addr))); memcpy(&result.info, ent, sizeof(result.info)); if (dns->fdh) ecore_main_fd_handler_del(dns->fdh); dns->fdh = NULL; dns->done_cb(dns->data, &result); free(ent); _ecore_con_dns_free(dns); } return 0; error: dns->done_cb(dns->data, NULL); _ecore_con_dns_free(dns); return -1; } static Eina_Bool _dns_fd_cb(Ecore_Con_DNS *dns, Ecore_Fd_Handler *fdh __UNUSED__) { if (_ecore_con_dns_check(dns) != 1) return ECORE_CALLBACK_RENEW; if (ecore_main_fd_handler_fd_get(dns->fdh) != dns_ai_pollfd(dns->ai)) { ecore_main_fd_handler_del(dns->fdh); dns->fdh = ecore_main_fd_handler_add(dns_ai_pollfd(dns->ai), dns_ai_events(dns->ai), (Ecore_Fd_Cb)_dns_fd_cb, dns, NULL, NULL); } else ecore_main_fd_handler_active_set(dns->fdh, dns_ai_events(dns->ai)); return ECORE_CALLBACK_RENEW; } static Eina_Bool _dns_timer_cb(Ecore_Con_DNS *dns) { dns->done_cb(dns->data, NULL); _ecore_con_dns_free(dns); dns->timer = NULL; return EINA_FALSE; }
static unsigned char em_init(Evas_Object *obj, void **emotion_video, Emotion_Module_Options *opt) { Emotion_Xine_Video *ev; int fds[2]; if (!emotion_video) return 0; ev = calloc(1, sizeof(Emotion_Xine_Video)); if (!ev) return 0; ev->obj = obj; if (pipe(fds) == 0) { ev->fd_read = fds[0]; ev->fd_write = fds[1]; fcntl(ev->fd_read, F_SETFL, O_NONBLOCK); ev->fd_handler = ecore_main_fd_handler_add(ev->fd_read, ECORE_FD_READ, _em_fd_active, ev, NULL, NULL); ecore_main_fd_handler_active_set(ev->fd_handler, ECORE_FD_READ); } if (pipe(fds) == 0) { ev->fd_ev_read = fds[0]; ev->fd_ev_write = fds[1]; fcntl(ev->fd_ev_read, F_SETFL, O_NONBLOCK); ev->fd_ev_handler = ecore_main_fd_handler_add(ev->fd_ev_read, ECORE_FD_READ, _em_fd_ev_active, ev, NULL, NULL); ecore_main_fd_handler_active_set(ev->fd_ev_handler, ECORE_FD_READ); } if (pipe(fds) == 0) { ev->fd_slave_read = fds[0]; ev->fd_slave_write = fds[1]; fcntl(ev->fd_slave_write, F_SETFL, O_NONBLOCK); } ev->volume = 0.8; ev->delete_me = 0; ev->get_pos_thread_deleted = 0; ev->opening = 1; ev->play_ok = 0; if (opt) { ev->opt_no_audio = opt->no_audio; ev->opt_no_video = opt->no_video; } pthread_cond_init(&(ev->get_pos_len_cond), NULL); pthread_mutex_init(&(ev->get_pos_len_mutex), NULL); pthread_create(&ev->get_pos_len_th, NULL, _em_get_pos_len_th, ev); pthread_create(&ev->slave_th, NULL, _em_slave, ev); pthread_detach(ev->slave_th); _em_slave_event(ev, 1, NULL); ev->buffer = 1.0; *emotion_video = ev; return 1; }