pidgin/plugins/crazychat/cc_network.c

branch
facebook
changeset 37384
3c5c8c63a686
parent 37383
72cb6af0a275
parent 37246
0ddd5118b8eb
child 37385
43ac0ab4b1d0
--- a/pidgin/plugins/crazychat/cc_network.c	Tue Sep 15 21:40:59 2015 -0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,540 +0,0 @@
-#include <assert.h>
-#include <errno.h>
-#include <string.h>
-#include <gtk/gtk.h>
-#include "conversation.h"
-#include "network.h"
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include "cc_network.h"
-#include "cc_interface.h"
-#include "util.h"
-
-/* --- begin constant definitions --- */
-
-#define NETWORK_TIMEOUT_DELAY	40		/* in ms */
-#define MAX_ACCEPT_CHECKS	1000
-
-/* --- begin type declarations --- */
-
-struct accept_args {
-	PurpleAccount *account;
-	struct crazychat *cc;
-	char *name;
-	guint32 peer_ip;
-	guint16 peer_port;
-};
-
-struct sock_accept_args {
-	PurpleAccount *account;
-	struct cc_session *session;
-};
-
-/* --- begin function prototypes --- */
-
-/**
- * Creates a server socket and sends a response to the peer.
- * @param account		the purple account sending the ready msg
- * @param session		the peer CrazyChat session
- */
-static void cc_net_send_ready(PurpleAccount *account, struct cc_session *session);
-
-/**
- * Handles responses from the CrazyChat session invite dialog box.
- * @param dialog		the dialog box
- * @param response		the dialog box button response
- * @param args			account, crazychat global data, peer name
- */
-static void invite_handler(GtkDialog *dialog, gint response,
-		struct accept_args *args);
-
-/**
- * Periodically checks the server socket for peer's connection.  Gives up
- * after a set number of checks.
- * @param args			peer session and account
- * @return			TRUE to continue checking, FALSE to stop
- */
-static gboolean accept_cb(struct sock_accept_args *args);
-
-/**
- * Initialize CrazyChat network session.  Sets up the UDP socket and port.
- * @param account		the account the session is part of
- * @param session		the CrazyChat network session
- */
-static void init_cc_net_session(PurpleAccount *account,
-		struct cc_session *session);
-
-/**
- * Handles checking the network for new feature data and sending out the
- * latest features.
- * @param session		the session we're checking for network traffic
- */
-static gboolean network_cb(struct cc_session *session);
-
-/**
- * Generates random bytes in the user specified byte buffer.
- * @param buf		the byte buffer
- * @param len		length of the byte buffer
- */
-static void generate_randomness(uint8_t buf[], unsigned int len);
-
-/**
- * Sends data over a socket.
- * @param s   socket file descriptor
- * @param buf data buffer
- * @param len data buffer length
- * @return    number of bytes sent or -1 if an error occurred
- */
-static int __send(int s, char *buf, int len);
-
-/* --- begin function definitions --- */
-
-void cc_net_send_invite(struct crazychat *cc, char *name, PurpleAccount *account)
-{
-	struct cc_session *session;
-	PurpleConversation *conv;
-	PurpleIMConversation *im;
-	char buf[BUFSIZ];
-
-	session = cc_find_session(cc, name);
-	if (session) return; /* already have a session with this guy */
-	session = cc_add_session(cc, name);
-	session->state = INVITE;
-	conv = purple_conversations_find_with_account(name, account);
-	if (!conv) {
-		conv = purple_im_conversation_new(account, name);
-	}
-	im = purple_conversation_get_im_data(conv);
-	snprintf(buf, BUFSIZ, "%s%s!%d", CRAZYCHAT_INVITE_CODE,
-		purple_network_get_my_ip(-1), cc->tcp_port);
-	Debug("Sent invite to %s for port: %d\n", name, cc->tcp_port);
-	purple_im_conversation_send(im, buf);
-}
-
-void cc_net_recv_invite(PurpleAccount *account, struct crazychat *cc, char *name,
-		const char *peer_ip, const char *peer_port)
-{
-	struct cc_session *session;
-	PurpleConversation *conv;
-	PurpleConvWindow *convwin;
-	char buf[BUFSIZ];
-	struct accept_args *args;
-
-	assert(cc);
-	assert(name);
-	Debug("Received a CrazyChat session invite from %s on port %s!\n",
-			name, peer_port);
-	session = cc_find_session(cc, name);
-	if (!session) {
-		Debug("Creating a CrazyChat session invite dialog box!\n");
-		conv = purple_conversations_find_with_account(name, account);
-		if (conv) convwin = purple_conversation_get_window(conv);
-		else convwin = NULL;
-		/* pop gtk window asking if want to accept */
-		GtkWidget *dialog =
-			gtk_dialog_new_with_buttons("CrazyChat Session Invite",
-			GTK_WINDOW(convwin),
-			GTK_DIALOG_MODAL |
-			GTK_DIALOG_DESTROY_WITH_PARENT,
-			GTK_STOCK_OK,
-			GTK_RESPONSE_ACCEPT,
-			GTK_STOCK_CANCEL,
-			GTK_RESPONSE_REJECT,
-			NULL);
-		snprintf(buf, BUFSIZ, "Would you like to CRaZYchAT with %s?", name);
-		GtkWidget *label = gtk_label_new(buf);
-		gtk_container_add(GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
-				label);
-		args = (struct accept_args*)malloc(sizeof(*args));
-		args->account = account;
-		args->cc = cc;
-		args->name = strdup(name);
-		assert(inet_aton(peer_ip, (struct in_addr*)&args->peer_ip));
-		args->peer_port = atoi(peer_port);
-
-		g_signal_connect(GTK_OBJECT(dialog), "response",
-				G_CALLBACK(invite_handler), args);
-
-		gtk_widget_show_all(dialog);
-	}
-}
-
-void cc_net_recv_accept(PurpleAccount *account, struct crazychat *cc, char *name,
-		const char *peer_ip)
-{
-	struct cc_session *session;
-	struct in_addr peer_addr;
-
-	assert(cc);
-	assert(name);
-	Debug("Received a CrazyChat session accept!\n");
-	session = cc_find_session(cc, name);
-	if (session && session->state == INVITE) {
-		session->state = ACCEPTED;
-		assert(inet_aton(peer_ip, &peer_addr));
-		session->peer_ip = peer_addr.s_addr;
-		cc_net_send_ready(account, session);
-	}
-}
-
-static void cc_net_send_ready(PurpleAccount *account, struct cc_session *session)
-{
-	struct sock_accept_args *args;
-
-	assert(session);
-	Debug("Initializing the server socket and sending ready message\n");
-	/* create the server socket */
-	session->tcp_sock = socket(AF_INET, SOCK_STREAM, 0);
-	assert(session->tcp_sock != -1);
-	int reuse = 1;
-	assert(setsockopt(session->tcp_sock, SOL_SOCKET, SO_REUSEADDR,
-				&reuse, sizeof(int)) != -1);
-	struct sockaddr_in my_addr;
-	my_addr.sin_family = AF_INET;
-	my_addr.sin_port = htons(session->cc->tcp_port);
-	assert(inet_aton(purple_network_get_my_ip(-1),
-			&my_addr.sin_addr));
-	memset(&my_addr.sin_zero, 0, sizeof(my_addr.sin_zero));
-	assert(bind(session->tcp_sock, (struct sockaddr*)&my_addr,
-				sizeof(my_addr)) != -1);
-	Debug("Listening on port: %d\n", my_addr.sin_port);
-	assert(listen(session->tcp_sock, 1) != -1);
-
-	/* socket created, send the ready message */
-	PurpleConversation *conv;
-	PurpleIMConversation *im;
-
-	conv = purple_conversations_find_with_account(session->name, account);
-	if (!conv) {
-		conv = purple_im_conversation_new(account,
-				session->name);
-	}
-	im = purple_conversation_get_im_data(conv);
-	purple_im_conversation_send(im, CRAZYCHAT_READY_CODE);
-
-	/* register timer callback for checking socket connection */
-	args = (struct sock_accept_args*)malloc(sizeof(*args));
-	args->session = session;
-	args->account = account;
-	session->udp_sock = MAX_ACCEPT_CHECKS;
-	session->timer_id = g_timeout_add(NETWORK_TIMEOUT_DELAY,
-		(GSourceFunc)accept_cb, args);
-}
-
-void cc_net_recv_ready(PurpleAccount *account, struct crazychat *cc, char *name)
-{
-	struct cc_session *session;
-	struct sockaddr_in server_addr, my_addr;
-	int sock;
-
-	assert(cc);
-	assert(name);
-	Debug("Received a CrazyChat session ready!\n");
-	session = cc_find_session(cc, name);
-	if (session && session->state == ACCEPTED) {
-		/* connect to peer */
-		session->tcp_sock = socket(AF_INET, SOCK_STREAM, 0);
-		assert(session->tcp_sock != -1);
-		server_addr.sin_family = AF_INET;
-		server_addr.sin_port = session->peer_port;
-		server_addr.sin_addr.s_addr = session->peer_ip;
-		memset(&(server_addr.sin_zero), 0,
-				sizeof(server_addr.sin_zero));
-		assert(connect(session->tcp_sock,
-				(struct sockaddr*)&server_addr,
-				sizeof(server_addr)) != -1);
-		Debug("Connecting to peer on port %d\n", session->peer_port);
-
-		/* now set state */
-		session->state = CONNECTED;
-		init_cc_net_session(account, session);
-	}
-}
-
-static void invite_handler(GtkDialog *dialog, gint response, struct accept_args *args)
-{
-	struct cc_session *session;
-	char buf[BUFSIZ];
-	PurpleConversation *conv;
-	PurpleIMConversation *im;
-
-	if (response == GTK_RESPONSE_ACCEPT) {
-		assert(args);
-		session = cc_find_session(args->cc, args->name);
-		assert(!session);
-		session = cc_add_session(args->cc, args->name);
-		session->state = ACCEPTED;
-		session->peer_ip = args->peer_ip;
-		session->peer_port = args->peer_port;
-		snprintf(buf, BUFSIZ, "%s%s", CRAZYCHAT_ACCEPT_CODE,
-			purple_network_get_my_ip(-1));
-		conv = purple_conversations_find_with_account(args->name,
-				args->account);
-		if (!conv) {
-			conv = purple_conversation_new(PURPLE_CONV_TYPE_IM,
-				args->account, args->name);
-		}
-		im = purple_conversation_get_im_data(conv);
-		purple_im_conversation_send(im, buf);
-	}
-	free(args->name);
-	free(args);
-	gtk_widget_destroy(GTK_WIDGET(dialog));
-}
-
-static gboolean accept_cb(struct sock_accept_args *args)
-{
-	fd_set fds;
-	struct timeval zero;
-	int ret;
-	PurpleAccount *account;
-	struct cc_session *session;
-
-	assert(args);
-	account = args->account;
-	session = args->session;
-	assert(account);
-	assert(session);
-
-	/* set select to check on our tcp socket */
-	FD_ZERO(&fds);
-	FD_SET(session->tcp_sock, &fds);
-	memset(&zero, 0, sizeof(zero));
-
-	/* check socket */
-	ret = select(session->tcp_sock+1,&fds, NULL, NULL, &zero);
-	assert(ret != -1);
-
-	if (ret) { /* got something to check */
-		Debug("Checking pending connection\n");
-		int sock;
-		struct sockaddr_in client_addr;
-		socklen_t sin_size;
-
-		sin_size = sizeof(client_addr);
-		sock = accept(session->tcp_sock,
-				(struct sockaddr*)&client_addr, &sin_size);
-		assert(sock != -1);
-
-		/* check if it's a match */
-		if (client_addr.sin_addr.s_addr == session->peer_ip) {
-			/* cool, we're set */
-			Debug("Accepted tcp connect from %s\n", session->name);
-			close(session->tcp_sock);
-			session->tcp_sock = sock;
-			session->state = CONNECTED;
-			session->timer_id = 0;
-			init_cc_net_session(account, session);
-			Debug("Will start sending to port %d\n",
-					session->peer_port);
-			free(args);
-			return FALSE;
-		}
-	}
-
-	session->udp_sock--;
-
-	if (!session->udp_sock) { /* timed out */
-		/* remove session from session list */
-		cc_remove_session(session->cc, session);
-		free(args);
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-static void init_cc_net_session(PurpleAccount *account,
-		struct cc_session *session)
-{
-	struct sockaddr_in my_addr;
-	struct sockaddr_in peer_addr;
-	int reuse;
-
-	/* send/obtain the udp port information */
-
-	assert(__send(session->tcp_sock, (char*)&session->cc->udp_port,
-			sizeof(session->cc->udp_port)) ==
-			sizeof(session->cc->udp_port));
-	assert(recv(session->tcp_sock, (char*)&session->peer_port,
-			sizeof(session->peer_port), 0) ==
-			sizeof(session->peer_port));
-
-	Debug("Established a CrazyChat session with %s!\n", session->name);
-
-	/* connect the udp sockets */
-
-	session->udp_sock = socket(AF_INET, SOCK_DGRAM, 0);
-
-	assert(!setsockopt(session->udp_sock, SOL_SOCKET, SO_REUSEADDR,
-			&reuse, sizeof(reuse)));
-
-	my_addr.sin_family = AF_INET;
-	my_addr.sin_port = htons(session->cc->udp_port);
-	assert(inet_aton(purple_network_get_my_ip(-1),
-				&my_addr.sin_addr));
-	memset(my_addr.sin_zero, 0, sizeof(my_addr.sin_zero));
-	assert(!bind(session->udp_sock, (struct sockaddr*)&my_addr,
-			sizeof(my_addr)));
-	session->peer.sin_family = AF_INET;
-	session->peer.sin_port = htons(session->peer_port);
-	session->peer.sin_addr.s_addr = session->peer_ip;
-	memset(&session->peer.sin_zero, 0, sizeof(session->peer.sin_zero));
-
-	Debug("Bound udp sock to port %d, connecting to port %d\n",
-		session->cc->udp_port, session->peer_port);
-
-	memset(&session->features, 0, sizeof(session->features));
-
-	session->output = init_output(&session->features, session);
-
-	session->filter = Filter_Initialize();
-
-	/* initialize timer callback */
-	session->timer_id = g_timeout_add(NETWORK_TIMEOUT_DELAY,
-		(GSourceFunc)network_cb, session);
-
-	/* initialize input subsystem if not initialized */
-	if (!session->cc->features_state) {
-		session->cc->input_data = init_input(session->cc);
-		session->cc->features_state = 1;
-	}
-}
-
-static gboolean network_cb(struct cc_session *session)
-{
-	fd_set fds;
-	struct timeval zero;
-	int ret;
-	int command;
-	struct cc_features *features;
-
-	assert(session);
-
-	Debug("Checking for data\n");
-
-	/* set select to check on our tcp socket */
-	FD_ZERO(&fds);
-	FD_SET(session->tcp_sock, &fds);
-	memset(&zero, 0, sizeof(zero));
-
-	/* check tcp socket */
-	ret = select(session->tcp_sock+1, &fds, NULL, NULL, &zero);
-	assert(ret != -1);
-
-	while (ret) {
-		ret = recv(session->tcp_sock, &command, sizeof(command), 0);
-		assert(ret != -1);
-		if (!ret) {
-			/* tcp connection closed, destroy connection */
-			gtk_widget_destroy(session->output->widget);
-			return FALSE;
-		}
-		assert(ret == sizeof(command));
-
-		FD_ZERO(&fds);
-		FD_SET(session->tcp_sock, &fds);
-		ret = select(session->tcp_sock+1, &fds, NULL, NULL, &zero);
-		assert(ret != -1);
-	}
-
-	/* set select to check on our udp socket */
-	FD_ZERO(&fds);
-	FD_SET(session->udp_sock, &fds);
-	memset(&zero, 0, sizeof(zero));
-
-	/* check udp socket */
-	ret = select(session->udp_sock+1, &fds, NULL, NULL, &zero);
-	assert(ret != -1);
-
-	features = &session->features;
-
-	while (ret) { /* have data, let's copy it for output */
-		struct sockaddr_in from;
-		int fromlen;
-		ret = recvfrom(session->udp_sock, &session->features,
-				sizeof(session->features),
-				0, (struct sockaddr*)&from, &fromlen);
-		Debug("Received %d bytes from port %d\n", ret,
-				ntohs(from.sin_port));
-		filter(features, session->filter);
-		Debug("\thead size: %d\n", features->head_size);
-		Debug("\topen: left(%s), right(%s), mouth(%s)\n",
-				features->left_eye_open ? "yes" : "no",
-				features->right_eye_open ? "yes" : "no",
-				features->mouth_open ? "yes" : "no");
-		Debug("\thead rotation: x(%d), y(%d), z(%d)\n",
-			features->head_x_rot, features->head_y_rot,
-			features->head_z_rot);
-		Debug("\tx(%d), y(%d)\n", features->x, features->y);
-		if (ret == -1) {
-			perror("wtf:");
-		}
-		assert(ret != -1);
-
-		FD_ZERO(&fds);
-		FD_SET(session->udp_sock, &fds);
-		ret = select(session->udp_sock+1, &fds, NULL, NULL, &zero);
-		assert(ret != -1);
-	}
-
-#ifdef _DISABLE_QT_
-	struct cc_features bogus;
-	features = &bogus;
-	generate_randomness((uint8_t*)features, sizeof(*features));
-#else
-	features = &session->cc->input_data->face;
-#endif
-	assert(sendto(session->udp_sock, (char*)features,
-			sizeof(*features), 0, (struct sockaddr*)&session->peer,
-			sizeof(session->peer)) == sizeof(*features));
-	Debug("Sent %d bytes\n", sizeof(*features));
-	Debug("\thead size: %d\n", features->head_size);
-	Debug("\topen: left(%s), right(%s), mouth(%s)\n",
-			features->left_eye_open ? "yes" : "no",
-			features->right_eye_open ? "yes" : "no",
-			features->mouth_open ? "yes" : "no");
-	Debug("\thead rotation: x(%d), y(%d), z(%d)\n",
-		features->head_x_rot, features->head_y_rot,
-		features->head_z_rot);
-	Debug("\tx(%d), y(%d)\n", features->x, features->y);
-
-	/* clear easter egg */
-	features->mode = 0;
-
-	return TRUE;
-}
-
-static void generate_randomness(uint8_t buf[], unsigned int len)
-{
-	int fd;
-
-	fd = open("/dev/random", O_RDONLY);
-	assert(fd != -1);
-
-	assert(read(fd, buf, len) == len);
-	close(fd);
-}
-
-static int __send(int s, char *buf, int len)
-{
-	int total = 0;		/* how many bytes we've sent */
-	int bytesleft = len;	/* how many we have left to send */
-	int n;
-
-	while (total < len) {
-		n = send(s, buf + total, bytesleft, 0);
-		if (n == -1) {
-			Debug("ERROR: %s\n", g_strerror(errno));
-			return -1;
-		}
-		total += n;
-		bytesleft -= n;
-	}
-
-	return total;
-}

mercurial