Simple Network Library
Simple network library | ||
---|---|---|
![]() | ||
Información general | ||
Tipo de programa | Biblioteca informática | |
Desarrollador | Jesús Hernández Gormaz (autor inicial) | |
Licencia | GPL (software libre) | |
Información técnica | ||
Programado en | C | |
Versiones | ||
Última versión estable | 0.0.1 (9 de Junio del 2009) | |
Última versión en pruebas | 0.0.0 (5 de Abril del 2009) | |
Enlaces | ||
Simple Network Library (SNL) es una biblioteca informatica desarrollada con el lenguaje C que proporcionan funciones para realizar operaciones de comunicación en red, la primera version de esta biblioteca fue acabada el 5 de abril de 2009.
Proporciona herramientas para el desarrollo de videojuegos y cualquier otra aplicación. Una de sus grandes virtudes es el tratarse de una biblioteca multiplataforma, soportando oficialmente los sistemas GNU/Linux y OpenSolaris, además de otras arquitecturas/sistemas como windows, MacOS, etc. Las siglas le vienen de Simple Network Library que se traduce como biblioteca de red simple. Desarrollada inicialmente por Jesús Hernández Gormaz, desarrollador de videojuegos para la plataforma GNU/Linux entre otros programas informáticos programados.
Soporta los protocolos de IP tanto de IPv4 como de IPv6 además de los protocolos de comunicación TCP y UDP.
La biblioteca se distribuye bajo la licencia GPL.
Ejemplos
Ejemplo del uso de SNL para programar un cliente HTTP usando TCP sobre IPv4 en C.
/*
testSNL Copyright (C) 2009 Jesús Hernández Gormaz
Fecha de creacion: 5 de abril del 2009 (Siglo XXI)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Este programa es software libre. Puede redistribuirlo y/o
modificarlo bajo los términos de la Licencia Pública General
de GNU según es publicada por la Free Software Foundation,
bien de la versión 3 de dicha Licencia o bien (según su
elección) de cualquier versión posterior.
Este programa se distribuye con la esperanza de que sea
útil, pero SIN NINGUNA GARANTÍA, incluso sin la garantía
MERCANTIL implícita o sin garantizar la CONVENIENCIA PARA UN
PROPÓSITO PARTICULAR. Para más detalles, véase la Licencia
Pública General de GNU.
Debería haber recibido una copia de la Licencia Pública
General junto con este programa. En caso contrario, escriba
a la Free Software Foundation, Inc., en 675 Mass Ave,
Cambridge, MA 02139, EEUU.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <SNL/SNL.h>
int main(int argc, char *argv[]){
if(argc < 2){
printf("Para usar este ejemplo de SNL debe de indicar un dominio");
printf(" despues del comando con el que ejecuta el programa, por");
printf(" ejemplo:\n %s www.fsf.org\n", argv[0]);
exit(-1);
}else{
/*la variable conexión guardara el identificador de la conexión
el cual deberemos de pasarlo a las funciones cuando enviemos
orecivamos datos, etc, etc, etc.*/
int conexion;
/*texto es el array que usaremos como buffer para enviar
y recibir datos, con medio kilobyte es suficiente ya que
normalmente las paginas pesan unos pocos kilobytes (sin
contar las imagenes) y asi nuestro ejemplo leera varias
veces el socket para poder recibir toda la pagina*/
char texto[512];
/*las dos variables siguientes son respectivamente para guardar
la direccion del host, la IP, y para guardar un texto con la
informacion de SNL*/
char direccion[512], informacion[501];
/*para trabajar con la conexión usaremos un grupo de conexiones
por ser mejor que trabajar con la conexión directamente
incluso cuando solo necesitamos una conexión, el grupo nos
permite comprobar si hay datos esperando que los leamos en
algun socket sin que la aplicación se quede a la espera de que
haya datos en el socket*/
grupo_conexiones *a;
/*mostramos en terminal un texto que indica que el programa
esta ejecutandose y que vamos a empezar con la conexion*/
printf("\nEjecucion\n");
/*empezamos a llenar texto con la peticion HTTP que enviaremos
despues*/
strcpy(&texto[0], "GET ");
/*mostramos en pantalla el host al que nos conectaremos*/
printf("Host: %s\n", argv[1]);
/*usamos la funcion de DNS para IPv6 de forma que si se
obtiene una direccion parecida a 1F::F0:AB es que la maquina en
la que ejecutamos este ejemplo ya funciona con IPv6, pero este
ejemplo es de IPv4, por lo que esta es la unica funcion de Ipv6
que usaremos en este ejemplo por ser la que más difiere de su
equivalente para IPv4, el primer argumento es la cadena donde
queremos guardar la direccion IP, el segundo el host, el tercero
es el servicio pero lo dejamos como null ya que no necesitamos
conocer el puerto del servicio ni el servicio de un puerto
en este ejemplo además de no haber modificado los ficheros de
configuracion del sistema para configurar este ejemplo como un
servicio (esto limita los puertos que podemos usar), el cuarto
la longitud maxima de la cadena de caracteres de la direccion
(igual que antes al obtener el texto de la informacion de SNL)
y el ultimo es la longitud del servicio, 0 como le pasamos NULL*/
SNL_DNS(&direccion[0], argv[1], NULL, 1023, 0);
/*imprimimos en la terminal el host y la Ipv6 obtenida*/
printf("DNS IPv6 obtenido para %s: %s\n", argv[1], &direccion[0]);
/*usamos la funcion de DNS para IPv4, el primer argumento es
donde se copiara la direccion IPv4 y el segundo el host*/
SNL_DNS_IPv4(&direccion[0], argv[1]);
/*igual que antes, mostramos el host y la IPv4 en pantalla*/
printf("DNS IPv4 obtenido para%s: %s\n", argv[1], &direccion[0]);
/*continuamos rellenando el buffer con la peticion GET de HTTP
que enviaremos*/
strcat(&texto[0], "http://");
strcat(&texto[0], argv[1]);
strcat(&texto[0], "/");
strcat(&texto[0], " HTTP/1.1\n\rHost: ");
strcat(&texto[0], argv[1]);
strcat(&texto[0], "\n\rAccept: text/html\n\rKeep-Alive: 300\n\rProxy-Connection: keep-alive\n\r\n\r");
/*iniciamos una conexión de TCP sobre IPv4 en la direccion IP
que obtuvimos antes en el puerto 80, el puerto usado para el
protocolo HTTP*/
conexion= SNL_conectar_TCP_IPv4(&direccion[0], 80);
/*comprobamos si conseguimos conectarnos*/
if(conexion == SIN_CONEXION){
printf("problemas conectando\n");
exit(-1);
}
printf("conectado\n");
/*creamos un nuevo grupo de conexiones indicando como conexión
de escucha SIN_CONEXION ya que en este ejemplo no aceptaremos
conexiones como si fuese un servidor*/
a= SNL_nuevo_grupo_conexiones(SIN_CONEXION);
/*añadimos la conexión abierta al grupo*/
SNL_nueva_conexion_grupo(conexion, a);
/*enviamos el buffer que preparamos con la peticion HTTP
y comprobamos que todo el buffer se enviara*/
if(SNL_enviar_grupo_TCP(a, &texto[0], strlen(&texto[0]), 0) == 0){
printf("enviado:\n\n");
printf("%s\n\n", &texto[0]);
}else{
exit(-1);
}
/*cambiamos el tiempo de espera del grupo a que suceda algo en
los sockets*/
SNL_tiempo_espera_grupo(a, 2, 0);
/*esta funcion se encargara de comprobar todas las conexiones
del grupo menos la conexión de escucha*/
SNL_comprobar_grupo_conexiones(a);
/*volvemos a cambiar el tiempo de espera del grupo para dar
mas tiempo al servidor para enviar la respuesta*/
SNL_tiempo_espera_grupo(a, 5, 500000);
/*imprimimos texto en la terminal*/
printf("Esperando respuesta del servidor:\n\n");
/*iniciamos un bucle while en el que la condicion es que
la conexión en la que ha sucedido algo del grupo sea
la conexión que iniciamos antes (esto siempre se cumplira
ya que es la unica del grupo, a no ser que no haya ninguna
y el retorno sea SIN_CONEXION*/
while(SNL_conexion_activa_grupo_conexiones(a) == conexion){
/*intentamos leer datos recividos en el socket y
comprobamos si da error al leer datos recividos lo
cual puede ser por que el servidor cerrase la conexión
si devuelve 0 o por error en la recepcion de los datos
o error en la conexión si es -1*/
if(SNL_recibir_TCP(conexion, &texto[0], 512, 0) <= 0){
printf("\n\nproblemas reciviendo datos del servidor,");
printf(" puede que el servidor hubiese cerrado la conexion");
/*salimos del bucle*/
break;
}else{
/*como conseguimos recibir datos los mostramos en
la terminal*/
printf("%s", &texto[0]);
}
/*comprobamos si no hay ninguna conexión que este aun
activa*/
if(SNL_comprobar_grupo_conexiones(a) == -1){
/*salimos del bucle*/
break;
}
}
printf("\n\nsi no se muestran datos recibidos desde el servidor puede ser");
printf(" que el tiempo de espera se excedio del esperado");
/*cerramos todas las conexiones del grupo y eliminamos el grupo
liberando la memoria ocupada por este*/
SNL_cerrar_grupo_conexiones(a);
printf("\n\ndesconectado\n");
/*copiamos a informacion el texto con la informacion de SNL
y el 500 indica que el array puede guardar como maximo una
cadena de 500 caracteres, sin contar el carácter nulo de fin
de cadena de caracteres*/
informacion_biblioteca_SNL(&informacion[0], 500);
/*mostramos la informacion de SNL obtenida al principio*/
printf("\n%s\n\n", &informacion[0]);
printf("El texto anterior cifrado:\n");
/*encriptamos el texto usando la funcion de cifrado de bits
iguales que tiene SNL, esto es solo para mostrar un ejemplo de
esta funcion*/
EncriptarTexto_CifradoBitsIguales(&informacion[0], "Free software as in freedom");
printf("\n%s\n\n", &informacion[0]);
printf("Fin\n");
}
exit(0);
}
Ejemplo del uso de SNL para programar un sencillo servidor usando TCP sobre IPv4 en C.
/*
chatserverSNL Copyright (C) 2009 Jesús Hernández Gormaz
Fecha de creacion: 8 de Junio del 2009 (Siglo XXI)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Este programa es software libre. Puede redistribuirlo y/o
modificarlo bajo los términos de la Licencia Pública General
de GNU según es publicada por la Free Software Foundation,
bien de la versión 3 de dicha Licencia o bien (según su
elección) de cualquier versión posterior.
Este programa se distribuye con la esperanza de que sea
útil, pero SIN NINGUNA GARANTÍA, incluso sin la garantía
MERCANTIL implícita o sin garantizar la CONVENIENCIA PARA UN
PROPÓSITO PARTICULAR. Para más detalles, véase la Licencia
Pública General de GNU.
Debería haber recibido una copia de la Licencia Pública
General junto con este programa. En caso contrario, escriba
a la Free Software Foundation, Inc., en 675 Mass Ave,
Cambridge, MA 02139, EEUU.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <SNL/SNL.h>
/*tipo de variable enumeracion para especificar un color de algo que el
programa debe comunicar al usuario*/
typedef enum color {NoColor, normal, rojo, cyan, verde, azul, negro, amarillo, \
blanco, gris_claro, marron, purpura, gris_oscuro, verde_claro, cyan_claro, \
rojo_claro, purpura_claro} color;
/*funcion que manda a la terminal secuencias de escape ANSI para borrar la pantalla y colocar el cursor al comienzo de la misma*/
int secuencia_borrar_terminal();
/*funcion que manda a la terminal secuencias de escape ANSI para dar formato de color al texto en la terminal (el cambio se mantiene hasta que se vuelva a cambiar)*/
int secuencia_color_terminal(color c);
int main(int argc, char *argv[]){
/*iniciamos las variables*/
int conexion, conexion_escucha, puerto, e=0, i=0, p=1;
unsigned long int numero_clientes=0;
char buffer[1537], direccion[21];
/* Esta sera la publicidad que mostrara el servidor*/
char publicidad[]="\n\nPublicidad del servidor:\nVisita www.snl.ya.st\n\n\n\0";
/*el grupo de conexiones, con uno es suficiente*/
grupo_conexiones *clientes;
/*esto es puramente por decoracion y que quede bonito,
solo borra la ventana de la terminal*/
secuencia_borrar_terminal();
/*escribimos en pantalla*/
printf("Conectando el servidor en el puerto 1500, espere.");
/*iniciamos una conexion de escucha (este ejemplo es usando IPv4,
pero con IPv6 es practicamente igual pero usando las funciones que no
acaban con _IPv4 el nombre de la funcion, consulte la documentacion para
más información*/
conexion_escucha= SNL_escuchar_TCP_IPv4(NULL, 1500, 20);
/*comprobamos que el servidor este conectado*/
if(conexion == SIN_CONEXION){
/*esta es otra funcion que simplemente es para que quede bonito el
ejemplo, imprime en pantalla una secuencia de escape ANSI que hace
que todo lo que se escriba despues se vea en rojo claro*/
secuencia_color_terminal(rojo_claro);
printf("Error iniciando la conexion del servidor en el puerto 1500.\n");
/*con esto hacemos que al escribir no se escriba en rojo en pantalla
sino en el color predeterminado*/
secuencia_color_terminal(NoColor);
return -1;
}else{
printf("Servidor conectado y aceptando clientes en el puerto ");
secuencia_color_terminal(cyan);
printf("1500");
secuencia_color_terminal(NoColor);
printf(".\n");
/*esto si nos interesa, iniciamos un nuevo grupo de conexiones
pasando como argumento la conexion que usaremos para escuchar
conexiones entrantes*/
clientes= SNL_nuevo_grupo_conexiones(conexion_escucha);
/*comprobamos que se creara el nuevo grupo*/
if(clientes == NULL){
/*esto es que no se a creado, lo indicamos y acabamos el
programa*/
secuencia_color_terminal(rojo_claro);
printf("Error de memoria insuficiente.\n");
secuencia_color_terminal(NoColor);
return -1;
}else{
/*se creo correctamente el grupo, cambiamos el tiempo de espera
a que suceda algo en los sockets del grupo a un segundo y
500000 microsegundos (un segundo y medio)*/
SNL_tiempo_espera_grupo(clientes, 1, 500000);
/*esto es un bucle con el que estar atendiendo a los clientes
continuamente sin que acabe el programa, deberemos acabarlo
pulsando CONTROL+C o cerrando la terminal*/
while(e == 0){
printf("Comprobando conexiones entrantes, espere.\n");
/*comprobamos si hay alguna conexion entrante*/
while(SNL_conexion_entrante_grupo(clientes) == 1){
printf("Nueva conexion entrante, espere.\n");
/*aceptamos la conexion entrante como un buen
servidor*/
conexion= SNL_aceptar_conexion_IPv4(conexion_escucha, &direccion[0], &puerto);
/*comprobamos que se ha podido establecer la
conexion*/
if(conexion == SIN_CONEXION){
secuencia_color_terminal(rojo_claro);
printf("Error aceptando conexion entrante.\n");
secuencia_color_terminal(NoColor);
}else{
printf("Conexion entrante nueva aceptada:\n");
secuencia_color_terminal(amarillo);
printf("%s %i\n", &direccion[0], puerto);
secuencia_color_terminal(NoColor);
/*añadimos la conexion al grupo de
conexiones y comprobamos que no
hubo errores*/
if(SNL_nueva_conexion_grupo(conexion, clientes) != 0){
secuencia_color_terminal(rojo_claro);
printf("Error de memoria en la conexion entrante.\n");
secuencia_color_terminal(NoColor);
}else{
printf("La nueva conexion entrante ha sido aceptada sin problemas.\n");
/*aumentamos el numero de clientes*/
numero_clientes++;
strcpy(&buffer[0], "Un cliente se ha conectado al servidor.\n");
strcat(&buffer[0], "IP del cliente que se ha conectado: ");
strcat(&buffer[0], &direccion[0]);
strcat(&buffer[0], "\n\0");
/*enviamos a todos los clientes
la direccion IP del nuevo
cliente y comprobamos que
no hubo ningun error enviando*/
if(SNL_enviar_grupo_TCP(clientes, &buffer[0], 1536, 0) == 0){
printf("Datos reenviados a todos los clientes sin problemas.\n");
}else{
secuencia_color_terminal(rojo_claro);
printf("Error reenviando datos a todos los clientes.\n");
secuencia_color_terminal(NoColor);
}
}
}
}
printf("Conexiones entrantes comprobadas.\n");
printf("Comprobando clientes conectados en busca de actividad en la conexion, espere.\n");
conexion= SIN_CONEXION;
/*comprobamos si hay alguna conexion activa en el
grupo de conexiones*/
if(SNL_comprobar_grupo_conexiones(clientes) == 0){
/*ahora obtenemos la conexion activa del grupo*/
conexion= SNL_conexion_activa_grupo_conexiones(clientes);
/*este bucle es para despues intentar obtener
otra conexion activa hasta atender a todas*/
while(conexion > SIN_CONEXION){
/*vaciamos el buffer, esto no es
relevante para el uso de SNL, pero
como este programa lo probare usando
telnet para conectarme a el consigo
asi que al enviar un mensaje no
muestre fragmentos de mensajes
anteriores*/
for(i=0; i<1537; i++){
buffer[i]= '\0';
}
/*recibimos los datos del cliente y
guardamos el valor retornado*/
i= SNL_recibir_TCP(conexion, &buffer[0], 1536, 0);
/*comprobamos que sucedio con el valor
retornado*/
if(i == 0){
printf("Desconexion del cliente.\n");
/*quitamos la conexion del grupo
como la funcion de recivir datos
ya la cerro automaticamente*/
if(SNL_quitar_conexion_grupo(conexion, clientes) == 0){
printf("Conexion cerrada sin problemas.\n");
/*ahora tenemos un cliente menos
conectado*/
numero_clientes--;
strcpy(&buffer[0], "Un cliente se ha desconectado del servidor.\n\0");
/*informamos de esto a los
demas clientes*/
if(SNL_enviar_grupo_TCP(clientes, &buffer[0], 1536, 0) == 0){
printf("Datos reenviados a todos los clientes sin problemas.\n");
}else{
secuencia_color_terminal(rojo_claro);
printf("Error reenviando datos a todos los clientes.\n");
secuencia_color_terminal(NoColor);
}
}else{
secuencia_color_terminal(rojo_claro);
printf("Error cerrando la conexion.\n");
secuencia_color_terminal(NoColor);
numero_clientes--;
strcpy(&buffer[0], "Un cliente se ha desconectado del servidor.\nOcurrio un error en la desconexion.\n\0");
if(SNL_enviar_grupo_TCP(clientes, &buffer[0], 1536, 0) == 0){
printf("Datos reenviados a todos los clientes sin problemas.\n");
}else{
secuencia_color_terminal(rojo_claro);
printf("Error reenviando datos a todos los clientes.\n");
secuencia_color_terminal(NoColor);
}
}
}else if(i == -1){
secuencia_color_terminal(rojo_claro);
printf("Error recibiendo datos del cliente.\n");
secuencia_color_terminal(NoColor);
strcpy(&buffer[0], "Ocurrio un error reciviendo datos de un cliente.\n\0");
/*informamos a todos los clientes
del error reciviendo los datos*/
if(SNL_enviar_grupo_TCP(clientes, &buffer[0], 1536, 0) == 0){
printf("Datos reenviados a todos los clientes sin problemas.\n");
}else{
secuencia_color_terminal(rojo_claro);
printf("Error reenviando datos a todos los clientes.\n");
secuencia_color_terminal(NoColor);
}
}else{
printf("Datos recividos del cliente:\n");
secuencia_color_terminal(verde);
printf("%s\n", &buffer[0]);
secuencia_color_terminal(NoColor);
printf("Reenviando datos a todos los clientes, espere.\n");
/*reenviamos los datos recividos
a todos los clientes*/
if(SNL_enviar_grupo_TCP(clientes, &buffer[0], 1536, 0) == 0){
printf("Datos reenviados a todos los clientes sin problemas.\n");
/*esto es para despues
mostrar publicidad*/
p++;
}else{
secuencia_color_terminal(rojo_claro);
printf("Error reenviando datos a todos los clientes.\n");
secuencia_color_terminal(NoColor);
}
}
/*este es el motivo del while dentro del
que estamos, comprobamos nuevamente
las conexiones activas para atender a
todas*/
conexion= SIN_CONEXION;
SNL_comprobar_grupo_conexiones(clientes);
conexion= SNL_conexion_activa_grupo_conexiones(clientes);
}
}
printf("Actividad en las conexiones comprobadas.\n");
/*esto se encarga de la publicidad*/
if(p >= 20){
p= 1;
strcpy(&buffer[0], &publicidad[0]);
strcat(&buffer[0], "Datos del servidor:\n - Ultima IP conectada: ");
strcat(&buffer[0], &direccion[0]);
strcat(&buffer[0], "\n\n\n\0");
if(SNL_enviar_grupo_TCP(clientes, &buffer[0], 1536, 0) == 0){
printf("Publicidad enviada a todos los clientes sin problemas.\n");
}else{
secuencia_color_terminal(rojo_claro);
printf("Error enviando publicidad a todos los clientes.\n");
secuencia_color_terminal(NoColor);
}
}
/*esto es tambien para que quede bonito, y para evitar
consumir demasiada CPU, para el programa 1 segundo,
esto en GNU/Linux funciona, pero en otros sistemas no
puedo asegurarlo, como no es relevante puede eliminarse
para compilar si da error solo que la pantalla de
la terminal parpadeara al borrar el texto y
escribir nuevamente*/
sleep(1);
secuencia_borrar_terminal();
printf("Servidor conectado y aceptando clientes en el puerto ");
secuencia_color_terminal(cyan);
printf("1500");
secuencia_color_terminal(NoColor);
printf(".\n");
printf("Total de clientes conectados: ");
secuencia_color_terminal(cyan);
printf("%lu", numero_clientes);
secuencia_color_terminal(NoColor);
printf(".\n");
printf("Ultimos datos recividos del cliente:\n");
secuencia_color_terminal(verde);
printf("%s", &buffer[0]);
secuencia_color_terminal(NoColor);
printf("\n");
}
return 0;
}
}
}
/*funcion que manda a la terminal secuencias de escape ANSI para borrar la pantalla y colocar el cursor al comienzo de la misma*/
int secuencia_borrar_terminal(){
printf("\n");
printf("%c[2J", 27);
printf("%c[0;0f", 27);
secuencia_color_terminal(normal);
return 0;
}
/*funcion que manda a la terminal secuencias de escape ANSI para dar formato de color al texto en la terminal (el cambio se mantiene hasta que se vuelva a cambiar)*/
int secuencia_color_terminal(color c){
register int r=0;
printf("%c[", 27);
switch(c){
case rojo: printf("0;31");
break;
case rojo_claro: printf("1;31");
break;
case verde: printf("0;32");
break;
case verde_claro: printf("1;32");
break;
case amarillo: printf("1;33");
break;
case marron: printf("0;33");
break;
case gris_oscuro: printf("1;30");
break;
case gris_claro: printf("0;37");
break;
case azul: printf("0;34");
break;
case purpura: printf("0;35");
break;
case purpura_claro: printf("1;35");
break;
case cyan: printf("0;36");
break;
case cyan_claro: printf("1;36");
break;
case blanco: printf("1;37");
break;
default: printf("0;00");
break;
}
printf("m");
return r;
}
Referencias
Bibliografía
Documentacion de SNL
- Jesús Hernández Gormaz (2009). Documentacion de SNL (1). p. 2.
Enlaces externos
- www.snl.ya.st - Página oficial de SNL.