diff --git a/legacy/ecore/doc/ecore.dox.in b/legacy/ecore/doc/ecore.dox.in index 1cee60c1ca..1b7bb82767 100644 --- a/legacy/ecore/doc/ecore.dox.in +++ b/legacy/ecore/doc/ecore.dox.in @@ -314,6 +314,11 @@ Shows how to set and retrieve the program arguments. Shows how to use event handlers. */ +/** +@example ecore_fd_handler_example.c +Shows how to use fd handlers. +*/ + /** @example ecore_timer_example.c Demonstrates use of the ecore_timer. diff --git a/legacy/ecore/examples/ecore_fd_handler_example.c b/legacy/ecore/examples/ecore_fd_handler_example.c new file mode 100644 index 0000000000..63aeb3068b --- /dev/null +++ b/legacy/ecore/examples/ecore_fd_handler_example.c @@ -0,0 +1,188 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Ecore_Fd_Handler example + * 2010 Mike Blumenkrantz + */ + +#define print(...) fprintf(stderr, "line %i: ", __LINE__); fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n") + +static int done = 0; + +static void +tls_log_func (int level, const char *str) +{ + fprintf (stderr, "|<%d>| %s", level, str); +} + +static const char* +SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_description_t status) +{ + switch (status) + { + case GNUTLS_HANDSHAKE_HELLO_REQUEST: + return "Hello request"; + case GNUTLS_HANDSHAKE_CLIENT_HELLO: + return "Client hello"; + case GNUTLS_HANDSHAKE_SERVER_HELLO: + return "Server hello"; + case GNUTLS_HANDSHAKE_NEW_SESSION_TICKET: + return "New session ticket"; + case GNUTLS_HANDSHAKE_CERTIFICATE_PKT: + return "Certificate packet"; + case GNUTLS_HANDSHAKE_SERVER_KEY_EXCHANGE: + return "Server key exchange"; + case GNUTLS_HANDSHAKE_CERTIFICATE_REQUEST: + return "Certificate request"; + case GNUTLS_HANDSHAKE_SERVER_HELLO_DONE: + return "Server hello done"; + case GNUTLS_HANDSHAKE_CERTIFICATE_VERIFY: + return "Certificate verify"; + case GNUTLS_HANDSHAKE_CLIENT_KEY_EXCHANGE: + return "Client key exchange"; + case GNUTLS_HANDSHAKE_FINISHED: + return "Finished"; + case GNUTLS_HANDSHAKE_SUPPLEMENTAL: + return "Supplemental"; + } + return NULL; +} + +/* Connects to the peer and returns a socket + * descriptor. + */ +static int +tcp_connect (void) +{ + const char *PORT = "443"; + const char *SERVER = "69.58.181.89"; //verisign.com + int err, sd; + int flag = 1, curstate = 0; + struct sockaddr_in sa; + + /* sets some fd options such as nonblock */ + fcntl(sd, F_SETFL, O_NONBLOCK); + fcntl(sd, F_SETFD, FD_CLOEXEC); + setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (const void *)&curstate, sizeof(curstate)); + + setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int)); + sd = socket (AF_INET, SOCK_STREAM, 0); + + memset (&sa, '\0', sizeof (sa)); + sa.sin_family = AF_INET; + sa.sin_port = htons (atoi (PORT)); + inet_pton (AF_INET, SERVER, &sa.sin_addr); + + /* connects to server + */ + err = connect (sd, (struct sockaddr *) &sa, sizeof (sa)); + if (err < 0) + { + fprintf (stderr, "Connect error\n"); + exit (1); + } + + return sd; +} + +/* closes the given socket descriptor. + */ +static void +tcp_close (int sd) +{ + shutdown (sd, SHUT_RDWR); /* no more receptions */ + close (sd); +} + +static Eina_Bool +_process_data(gnutls_session_t client, Ecore_Fd_Handler *fd_handler) +{ + static int ret, lastret; + + if (!done) + { + lastret = ret; + ret = gnutls_handshake (client); + /* avoid printing messages infinity times */ + if (lastret != ret) + { + 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!"); + ecore_main_loop_quit(); + } + + return ECORE_CALLBACK_RENEW; +} + +int +main (void) +{ + /* credentials */ + gnutls_anon_client_credentials_t c_anoncred; + gnutls_certificate_credentials_t c_certcred; + + gnutls_session_t client; + int sd; + + /* General init. */ + gnutls_global_init (); + ecore_init(); + gnutls_global_set_log_function (tls_log_func); + gnutls_global_set_log_level (6); + + /* Init client */ + gnutls_anon_allocate_client_credentials (&c_anoncred); + gnutls_certificate_allocate_credentials (&c_certcred); + gnutls_init (&client, GNUTLS_CLIENT); + /* set very specific priorities */ + gnutls_priority_set_direct(client, "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", NULL); + gnutls_credentials_set (client, GNUTLS_CRD_ANON, c_anoncred); + gnutls_credentials_set (client, GNUTLS_CRD_CERTIFICATE, c_certcred); + + + /* connect to the peer + */ + sd = tcp_connect (); + + /* associate gnutls with socket */ + gnutls_transport_set_ptr (client, (gnutls_transport_ptr_t) sd); + /* add a callback for data being available for send/receive on socket */ + if (!ecore_main_fd_handler_add(sd, ECORE_FD_READ | ECORE_FD_WRITE, (Ecore_Fd_Cb)_process_data, client, NULL, NULL)) + { + print("could not create fd handler!"); + exit(1); + } + /* begin main loop */ + ecore_main_loop_begin(); + + gnutls_bye (client, GNUTLS_SHUT_RDWR); + + gnutls_deinit (client); + + tcp_close (sd); + + return 0; +}