⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sock.c

📁 GNOME下的短信息发送中心
💻 C
字号:
/* * should be used by all gsms network code to support timeouts * and esy porting * * Authors:     Michael Jochum <e9725005@stud3.tuwien.ac.at> *              Gerhard Khueny <e9625442@student.tuwien.ac.at> * TODO:         * * Fixes: * * For license terms, see the file COPYING in the project directory. */#include <stdio.h>#include <unistd.h>#include <fcntl.h>#include <string.h>#include <errno.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/time.h>#include <netinet/in.h>#include <netdb.h>#include <signal.h>#include <assert.h>/* #include <gnome-i18n.h> */#include <gnome.h>#include <glib.h>#include "sock.h"#ifndef SOCKET_LOG_DOMAIN#define SOCKET_LOG_DOMAIN "SOCKET" #endif/* calls select and waits for input on s */static gint wait_for_data(const GSmsSocket * s){	fd_set read_fd_set;	struct timeval tv;	gint res;	tv.tv_sec = s->timeout;	tv.tv_usec = 0;	FD_ZERO(&read_fd_set);	FD_SET(s->fd, &read_fd_set);	/* Block until input arrives or time is up. */	res = select(s->fd + 1, &read_fd_set, NULL, NULL, &tv);	if (res == 0) {		g_log(SOCKET_LOG_DOMAIN, G_LOG_LEVEL_WARNING,		      _("Timeout while reading from socket"));		return GSMS_SOCKET_ERR_TIMEOUT;	}	if (res < 0) {		g_log(SOCKET_LOG_DOMAIN, G_LOG_LEVEL_WARNING,		      _("Error reading from socket (select): %s"),		      strerror(errno));		return GSMS_SOCKET_ERR_ERRNO;	}	return GSMS_SOCKET_SUCCESS;}/* allocate socket struct, set timout and create the socket */GSmsSocket *gsms_socket_create(gint timeout){	GSmsSocket *s;	s = g_new(GSmsSocket, 1);	s->timeout = timeout;	g_log(SOCKET_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,	      _("Creating new socket with %ds timeout."), timeout);	/* Create the socket.  */	if ((s->fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {		g_free(s);		g_log(SOCKET_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,		      _("Creating socket."));		return NULL;	}	return s;}/* open connection - connecto to a specified host *//* TODO: Timeout for gethostbyname (not easy) */gint gsms_socket_open_connection(const GSmsSocket * s,				 const gchar * host, const guint16 port){	struct sockaddr_in servername;	struct hostent *hostinfo;	gint flags;	fd_set write_fd_set;	struct timeval tv;	gint res;	g_return_val_if_fail(s != NULL, GSMS_SOCKET_ERR);	g_return_val_if_fail(host != NULL, GSMS_SOCKET_ERR);	/* resolv hostname --- TODO: add timeout */	g_log(SOCKET_LOG_DOMAIN, G_LOG_LEVEL_INFO,	      _("Resolving hostname for %s"), host);	hostinfo = gethostbyname(host);	if (hostinfo == NULL)		return GSMS_SOCKET_ERR_UNKNOWN_HOST;	/* connetct to host with timeout */	servername.sin_family = AF_INET;	servername.sin_port = htons(port);	servername.sin_addr = *(struct in_addr *) hostinfo->h_addr;	g_log(SOCKET_LOG_DOMAIN, G_LOG_LEVEL_INFO,	      _("Connecting to host %s:%d"), host, port);	/* Get the flags (should all be 0?) */	flags = fcntl(s->fd, F_GETFL, 0);	if (flags == -1) {		g_log(SOCKET_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,		      _("could not get flags for network socket"));		return GSMS_SOCKET_ERR;	}	if (fcntl(s->fd, F_SETFL, flags | O_NONBLOCK) == -1) {		g_log(SOCKET_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,		      _("could not set nonblocking mode for network socket"));		return GSMS_SOCKET_ERR;	}	/* Connect (but non-blocking!) */	res = connect(s->fd, (struct sockaddr *) &servername,		      sizeof(servername));	if (res < 0) {		if (errno != EINPROGRESS) {			g_log(SOCKET_LOG_DOMAIN, G_LOG_LEVEL_WARNING,			      _("error connecting %s:%d : %s"),			      host, port, strerror(errno));			return GSMS_SOCKET_ERR_ERRNO;		}	}	tv.tv_sec = s->timeout;	tv.tv_usec = 0;	FD_ZERO(&write_fd_set);	FD_SET(s->fd, &write_fd_set);	/* Block until input arrives or time is up. */	res = select(s->fd + 1, NULL, &write_fd_set, NULL, &tv);	if (res == 0) {		g_log(SOCKET_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,		      _("Timeout while trying to connect to %s:%d"), host,		      port);		return GSMS_SOCKET_ERR_TIMEOUT;	}	if (res < 0) {		g_log(SOCKET_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,		      _("select failed while connecting to host %s:%d : %s"),		      host, port, strerror(errno));		return GSMS_SOCKET_ERR_ERRNO;	}	if (FD_ISSET(s->fd, &write_fd_set)) {		gint error, len;		len = sizeof(error);		/* Get the error option */		if (getsockopt		    (s->fd, SOL_SOCKET, SO_ERROR, (void *) &error,		     &len) >= 0) {			/* Check if there is an error */			if (!error) {				/* Reset the flags */				if (fcntl(s->fd, F_SETFL, flags) == 0) {					return GSMS_SOCKET_SUCCESS;				}			}		}	}	g_log(SOCKET_LOG_DOMAIN, G_LOG_LEVEL_WARNING,	      _("could not connect to %s:%d : %s"),	      host, port, strerror(errno));	return GSMS_SOCKET_ERR;}/* close socket and free struct */gint gsms_socket_close(GSmsSocket * s){	g_return_val_if_fail(s != NULL, GSMS_SOCKET_ERR);	close(s->fd);	g_free(s);	return GSMS_SOCKET_SUCCESS;}/* set the socket timeout in seconds */void gsms_socket_set_timeout(GSmsSocket * s, guint timeout){	g_return_if_fail(s != NULL);	s->timeout = timeout;	return;}/* reads up to len bytes from s and saves them into buffer */gint gsms_socket_read(const GSmsSocket * s, gchar * buffer, gint len){	int res;	g_return_val_if_fail(s != NULL, GSMS_SOCKET_ERR);	g_return_val_if_fail(buffer != NULL, GSMS_SOCKET_ERR);	g_return_val_if_fail(len > 0, GSMS_SOCKET_ERR);	res = wait_for_data(s);	if (res < 0)		return res;	res = read(s->fd, buffer, len);	if (res < 0) {		g_log(SOCKET_LOG_DOMAIN, G_LOG_LEVEL_WARNING,		      _("Error reading from socket: %s"), strerror(errno));		return GSMS_SOCKET_ERR_ERRNO;	}	return res;}/* writes up to len bytes to the socket *//* returnes bytes written */gint gsms_socket_write(const GSmsSocket * s, gchar * buffer, gint len){	int res;	fd_set write_fd_set;	struct timeval tv;	g_return_val_if_fail(s != NULL, GSMS_SOCKET_ERR);	g_return_val_if_fail(buffer != NULL, GSMS_SOCKET_ERR);	g_return_val_if_fail(len > 0, GSMS_SOCKET_ERR);	tv.tv_sec = s->timeout;	tv.tv_usec = 0;	FD_ZERO(&write_fd_set);	FD_SET(s->fd, &write_fd_set);	/* Block until input arrives or time is up. */	res = select(s->fd + 1, NULL, &write_fd_set, NULL, &tv);	if (res == 0) {		g_log(SOCKET_LOG_DOMAIN, G_LOG_LEVEL_WARNING,		      _("write timed out"));		return GSMS_SOCKET_ERR_TIMEOUT;	}	if (res < 0) {		g_log(SOCKET_LOG_DOMAIN, G_LOG_LEVEL_WARNING,		      _("Error writing to socket (select): %s"),		      strerror(errno));		return GSMS_SOCKET_ERR_ERRNO;	}	res = write(s->fd, buffer, len);	if (res < 0) {		g_log(SOCKET_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,		      _("Error writng to socket: %s"), strerror(errno));		return GSMS_SOCKET_ERR_ERRNO;	}	return res;}/* Reads data up to the next newline.   If no newline is found within len bytes   len bytes from s are returned. */gint gsms_socket_read_line(const GSmsSocket * s, gchar * buffer, gint len){	gint n;	gchar *newline;	g_return_val_if_fail(s != NULL, GSMS_SOCKET_ERR);	g_return_val_if_fail(buffer != NULL, GSMS_SOCKET_ERR);	g_return_val_if_fail(len > 0, GSMS_SOCKET_ERR);	len--;	n = wait_for_data(s);	if (n < 0)		return n;	/* get next data but leave them in the network input buffer */	if ((n = recv(s->fd, buffer, len, MSG_PEEK)) <= 0) {		g_log(SOCKET_LOG_DOMAIN, G_LOG_LEVEL_WARNING,		      _("Error reading line from socket (recv): %s"),		      strerror(errno));		return GSMS_SOCKET_ERR_ERRNO;	}	if ((newline = (char *) memchr(buffer, '\n', n)) != NULL)		n = newline - buffer + 1;	if ((n = read(s->fd, buffer, n)) == -1) {		g_log(SOCKET_LOG_DOMAIN, G_LOG_LEVEL_WARNING,		      _("Error reading line from socket: %s"),		      strerror(errno));		return GSMS_SOCKET_ERR_ERRNO;	}	buffer += n;	*buffer = '\0';	return n;}gint gsms_socket_write_str(const GSmsSocket * s, gchar * buffer){	g_return_val_if_fail(s != NULL, GSMS_SOCKET_ERR);	g_return_val_if_fail(buffer != NULL, GSMS_SOCKET_ERR);	return gsms_socket_write(s, buffer, strlen(buffer));}/* read exactly len bytes from input */gint gsms_socket_read_block(const GSmsSocket * s, gchar * buf, gint len){	gint res;	gint bytes_read = 0;	g_return_val_if_fail(s != NULL, GSMS_SOCKET_ERR);	g_return_val_if_fail(buf != NULL, GSMS_SOCKET_ERR);	g_return_val_if_fail(len > 0, GSMS_SOCKET_ERR);	while ((res = gsms_socket_read(s, buf, len)) > 0) {		buf += res;		bytes_read += res;		len -= res;		if (len == 0)			break;		g_return_val_if_fail(len > 0, GSMS_SOCKET_ERR);	}	if (res < 0)		return res;	return bytes_read;}/* write eaxtly len bytes */gint gsms_socket_write_block(const GSmsSocket * s, gchar * buf, gint len){	gint res;	g_return_val_if_fail(s != NULL, GSMS_SOCKET_ERR);	g_return_val_if_fail(buf != NULL, GSMS_SOCKET_ERR);	g_return_val_if_fail(len > 0, GSMS_SOCKET_ERR);	while ((res = gsms_socket_write(s, buf, len)) < len) {		buf += res;		len -= res;		if (len == 0)			break;		g_return_val_if_fail(len > 0, GSMS_SOCKET_ERR);	}	if (res < 0)		return res;	return GSMS_SOCKET_SUCCESS;}gint gsms_socket_printf(const GSmsSocket * s, gchar * format, ...){	va_list ap;	gchar *buf;	gint res;	g_return_val_if_fail(s != NULL, GSMS_SOCKET_ERR);	g_return_val_if_fail(format != NULL, GSMS_SOCKET_ERR);	va_start(ap, format);	buf = g_strdup_vprintf(format, ap);	res = gsms_socket_write_str(s, buf);	g_free(buf);	return res;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -