diff options
Diffstat (limited to 'src/libgsmd')
| -rw-r--r-- | src/libgsmd/lgsm_internals.h | 9 | ||||
| -rw-r--r-- | src/libgsmd/libgsmd.c | 45 | ||||
| -rw-r--r-- | src/libgsmd/libgsmd_passthrough.c | 65 | 
3 files changed, 117 insertions, 2 deletions
diff --git a/src/libgsmd/lgsm_internals.h b/src/libgsmd/lgsm_internals.h index 66fd5fe..0601959 100644 --- a/src/libgsmd/lgsm_internals.h +++ b/src/libgsmd/lgsm_internals.h @@ -1,4 +1,13 @@ +#ifndef _LGSM_INTERNALS_H +#define _LGSM_INTERNALS_H + +#include <gsmd/usock.h> + +typedef int lgsm_msg_handler(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh);  struct lgsm_handle {  	int fd; +	lgsm_msg_handler *handler[__NUM_GSMD_MSGS];  }; + +#endif /* _LGSM_INTERNALS_H */ diff --git a/src/libgsmd/libgsmd.c b/src/libgsmd/libgsmd.c index 77b8499..104a8b3 100644 --- a/src/libgsmd/libgsmd.c +++ b/src/libgsmd/libgsmd.c @@ -36,7 +36,6 @@ static int lgsm_get_packet(struct lgsm_handle *lh)  	return 0;  } -  static int lgsm_open_backend(struct lgsm_handle *lh, const char *device)  {  	int rc; @@ -52,7 +51,6 @@ static int lgsm_open_backend(struct lgsm_handle *lh, const char *device)  		memset(&sun, 0, sizeof(sun));  		sun.sun_family = AF_UNIX;  		memcpy(sun.sun_path, GSMD_UNIX_SOCKET, sizeof(GSMD_UNIX_SOCKET)); -		printf("sizeof(GSMD_UNIX_SOCKET) = %u\n", sizeof(GSMD_UNIX_SOCKET));  		rc = connect(lh->fd, (struct sockaddr *)&sun, sizeof(sun));  		if (rc < 0) { @@ -66,6 +64,49 @@ static int lgsm_open_backend(struct lgsm_handle *lh, const char *device)  	return 0;  } +/* handle a packet that was received on the gsmd socket */ +int lgsm_handle_packet(struct lgsm_handle *lh, char *buf, int len) +{ +	struct gsmd_msg_hdr *gmh = (struct gsmd_msg_hdr *)buf; +	if (len < sizeof(*gmh)) +		return -EINVAL; +	 +	if (len - sizeof(*gmh) < gmh->len) +		return -EINVAL; +	 +	if (gmh->msg_type >= __NUM_GSMD_MSGS) +		return -EINVAL; +	 +	return lh->handler[gmh->msg_type](lh, gmh); +} + +/* blocking read and processing of packets until packet matching 'id' is found */ +int lgsm_blocking_wait_packet(struct lgsm_handle *lh, u_int16_t id,  +			      struct gsmd_msg_hdr *gmh, int rlen) +{ +	int rc; +	fd_set readset; + +	FD_ZERO(&readset); + +	while (1) { +		FD_SET(lh->fd, &readset); +		rc = select(lh->fd+1, &readset, NULL, NULL, NULL); +		if (rc <= 0) +			return rc; + +		rc = read(lh->fd, (char *)gmh, rlen); +		if (rc <= 0) +			return rc; + +		if (gmh->id == id) { +			/* we've found the matching packet, return to calling function */ +			return rc; +		} else +			rc = lgsm_handle_packet(lh, (char *)gmh, rc); +	} +} +  int lgsm_fd(struct lgsm_handle *lh)  {  	return lh->fd; diff --git a/src/libgsmd/libgsmd_passthrough.c b/src/libgsmd/libgsmd_passthrough.c new file mode 100644 index 0000000..45ce066 --- /dev/null +++ b/src/libgsmd/libgsmd_passthrough.c @@ -0,0 +1,65 @@ +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include <sys/types.h> + +#include <gsmd/usock.h> +#include <libgsmd/libgsmd.h> + +#include "lgsm_internals.h" + +static u_int16_t next_msg_id; + +static int lgsm_send(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh) +{ +	gmh->id = next_msg_id++; +	return send(lh->fd, (char *) gmh, sizeof(*gmh) + gmh->len); +} + +#define PT_BUF_SIZE	1024 +static char passthrough_buf[sizeof(struct gsmd_msg_hdr)+PT_BUF_SIZE]; +static char passthrough_rbuf[sizeof(struct gsmd_msg_hdr)+PT_BUF_SIZE]; + +int lgsm_passthrough(struct lgsm_handle *lh, const char *tx, char *rx, unsigned int *rx_len) +{ +	struct gsmd_msg_hdr *gmh = (struct gsmd_msg_hdr *)passthrough_buf; +	struct gsmd_msg_hdr *rgmh = (struct gsmd_msg_hdr *)passthrough_rbuf; +	char *tx_buf = (char *)gmh + sizeof(*gmh); +	char *rx_buf = (char *)rgmh + sizeof(*rgmh); +	int len = strlen(tx); +	int rc; + +	if (len > PT_BUF_SIZE) +		return -EINVAL; + +	gmh->version = GSMD_PROTO_VERSION; +	gmh->msg_type = GSMD_MSG_PASSTHROUGH; +	gmh->msg_subtype = GSMD_PASSTHROUGH_REQUEST; +	gmh->len = len; +	strcpy(tx_buf, tx); + +	rc = lgsm_send(lh, gmh); +	if (rc < len+sizeof(*gmh)) +		return rc; + +	/* since we synchronously want to wait for a response, we need to _internally_ loop over +	 * incoming packets and call the callbacks for intermediate messages (if applicable) */ +	rc = lgsm_blocking_wait_packet(lh, gmh->id, passthrough_rbuf, sizeof(passthrough_rbuf)); +	if (rc <= 0) +		return rc; + +	if (rc < sizeof(*rgmh)) +		return -EINVAL; + +	if (rc < sizeof(*rgmh) + rgmh->len) +		return -EINVAL; +	 +	/* FIXME: make sure rx_buf is zero-terminated */ +	strcpy(rx, rx_buf); +	*rx_len = rgmh->len; + +	return rx_len; +}  | 
