From: Philippe Nunes <philippe.nunes@linux.intel.com>
To: ofono@ofono.org
Subject: [PATCH v4 8/8] stk: Add read/write handlers
Date: Fri, 20 May 2011 18:26:21 +0200 [thread overview]
Message-ID: <1305908781-8322-8-git-send-email-philippe.nunes@linux.intel.com> (raw)
In-Reply-To: <1305908781-8322-1-git-send-email-philippe.nunes@linux.intel.com>
[-- Attachment #1: Type: text/plain, Size: 7470 bytes --]
---
src/stk.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 161 insertions(+), 10 deletions(-)
diff --git a/src/stk.c b/src/stk.c
index fbd93c3..72ca936 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -29,6 +29,8 @@
#include <stdlib.h>
#include <stdint.h>
#include <arpa/inet.h>
+#include <unistd.h>
+#include <fcntl.h>
#include <glib.h>
#include <gdbus.h>
@@ -89,6 +91,10 @@ struct ofono_stk {
gboolean report_channel_status;
struct ofono_gprs *gprs;
struct stk_bearer_description bearer_desc;
+ enum stk_transport_protocol_type protocol;
+ struct sockaddr_in dest_addr;
+ GIOChannel *io;
+ guint read_watch;
};
struct envelope_op {
@@ -573,6 +579,9 @@ static void stk_close_channel(struct ofono_stk *stk)
{
int err;
+ if (stk->read_watch > 0)
+ g_source_remove(stk->read_watch);
+
err = __ofono_gprs_remove_pdp_context(stk->gprs, stk->channel.id,
ofono_stk_remove_pdp_context_cb, stk);
@@ -636,6 +645,74 @@ static void stk_alpha_id_unset(struct ofono_stk *stk)
stk_agent_request_cancel(stk->current_agent);
}
+gsize stk_channel_data_write(struct ofono_stk *stk)
+{
+ GIOStatus status;
+ gsize bytes_written;
+ gchar *data = (gchar *)(stk->tx_buffer.data.array);
+ gsize count = stk->tx_buffer.data.len - stk->tx_buffer.tx_avail;
+
+ if (stk->protocol == STK_TRANSPORT_PROTOCOL_UDP_CLIENT_REMOTE) {
+ bytes_written = sendto(g_io_channel_unix_get_fd(stk->io), data,
+ count, 0, &stk->dest_addr,
+ sizeof(stk->dest_addr));
+
+ if (bytes_written == -1 && stk->read_watch > 0) {
+ g_source_remove(stk->read_watch);
+ return 0;
+ }
+ } else {
+ status = g_io_channel_write_chars(stk->io, data,
+ count, &bytes_written, NULL);
+
+ if (status != G_IO_STATUS_NORMAL && stk->read_watch > 0) {
+ g_source_remove(stk->read_watch);
+ return 0;
+ }
+ }
+
+ DBG("Send %zd bytes", bytes_written);
+
+ stk->tx_buffer.tx_avail += bytes_written;
+ count = stk->tx_buffer.data.len - stk->rx_buffer.tx_avail;
+ if (count > 0)
+ memmove(stk->tx_buffer.data.array, stk->rx_buffer.data.array +
+ bytes_written, count);
+
+ return bytes_written;
+}
+
+static gboolean receive_callback(GIOChannel *channel, GIOCondition cond,
+ gpointer userdata)
+{
+ struct ofono_stk *stk = (struct ofono_stk *) userdata;
+ GIOStatus status;
+ gsize bytes_read;
+ gchar *buf = (gchar *)(stk->rx_buffer.data.array +
+ stk->rx_buffer.rx_remaining);
+ gsize count = stk->rx_buffer.data.len - stk->rx_buffer.rx_remaining;
+
+ if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP))
+ return FALSE;
+
+ if (cond & G_IO_IN) {
+ status = g_io_channel_read_chars(channel, buf, count,
+ &bytes_read, NULL);
+ DBG("Received %zd bytes", bytes_read);
+
+ if (bytes_read > 0 && stk->rx_buffer.rx_remaining == 0 &&
+ stk->report_data_available) {
+ stk_send_data_available_event(stk, bytes_read);
+ }
+
+ stk->rx_buffer.rx_remaining += bytes_read;
+
+ if (status != G_IO_STATUS_NORMAL && status != G_IO_STATUS_AGAIN)
+ return FALSE;
+ }
+ return TRUE;
+}
+
static void ofono_stk_activate_pdp_context_cb(int error, const char *interface,
const char *ip,
void *data)
@@ -643,6 +720,8 @@ static void ofono_stk_activate_pdp_context_cb(int error, const char *interface,
struct ofono_stk *stk = data;
struct stk_response rsp;
struct ofono_error failure = { .type = OFONO_ERROR_TYPE_FAILURE };
+ GIOChannel *io;
+ int sk;
DBG("");
@@ -656,6 +735,67 @@ static void ofono_stk_activate_pdp_context_cb(int error, const char *interface,
stk->channel.status = STK_CHANNEL_PACKET_DATA_SERVICE_ACTIVATED;
}
+ if (stk->protocol == STK_TRANSPORT_PROTOCOL_TCP_CLIENT_REMOTE) {
+ sk = socket(AF_INET, SOCK_STREAM, 0);
+ if (sk < 0) {
+ rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+ goto out;
+ }
+
+ error = connect(sk, (struct sockaddr *) &stk->dest_addr,
+ sizeof(stk->dest_addr));
+
+ if (error < 0) {
+ close(sk);
+ rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+ goto out;
+ }
+ } else if (stk->protocol == STK_TRANSPORT_PROTOCOL_UDP_CLIENT_REMOTE) {
+ struct sockaddr_in addr;
+
+ sk = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sk < 0) {
+ rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+ goto out;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ addr.sin_port = htons(0);
+
+ error = bind(sk, (struct sockaddr *) &addr, sizeof(addr));
+ if (error < 0) {
+ close(sk);
+ rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+ goto out;
+ }
+ } else {
+ /* raw IP */
+ sk = open(interface, O_RDWR);
+ if (sk < 0)
+ return;
+ }
+
+ io = g_io_channel_unix_new(sk);
+ if (io == NULL) {
+ close(sk);
+ error = -ENOMEM;
+ rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+ goto out;
+ }
+
+ g_io_channel_set_close_on_unref(io, TRUE);
+ g_io_channel_set_flags(io, G_IO_FLAG_NONBLOCK, NULL);
+ g_io_channel_set_encoding(io, NULL, NULL);
+ g_io_channel_set_buffered(io, FALSE);
+
+ stk->read_watch = g_io_add_watch_full(io, G_PRIORITY_DEFAULT,
+ G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ receive_callback, stk, NULL);
+ stk->io = io;
+ g_io_channel_unref(io);
+
if (stk->pending_cmd == NULL) {
if (stk->report_channel_status)
stk_send_channel_status_event(stk);
@@ -670,11 +810,13 @@ static void ofono_stk_activate_pdp_context_cb(int error, const char *interface,
sizeof(struct stk_bearer_description));
} else if (stk->pending_cmd->type == STK_COMMAND_TYPE_SEND_DATA &&
stk->link_on_demand) {
- /*
- * TODO
- * send the data immediately, flush the tx buffer
- */
-
+ while (stk->tx_buffer.data.len - stk->tx_buffer.tx_avail) {
+ if (stk_channel_data_write(stk) == 0) {
+ ofono_error("Failed to send data");
+ rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+ goto out;
+ }
+ }
rsp.send_data.tx_avail = stk->tx_buffer.tx_avail;
}
@@ -711,6 +853,11 @@ static void stk_open_channel(struct ofono_stk *stk)
memset(host, 0, sizeof(host));
addr.s_addr = oc->data_dest_addr.addr.ipv4;
inet_ntop(AF_INET, &addr, host, INET_ADDRSTRLEN);
+
+ memset(&stk->dest_addr, 0, sizeof(stk->dest_addr));
+ stk->dest_addr.sin_family = AF_INET;
+ stk->dest_addr.sin_port = htons(oc->uti.port);
+ stk->dest_addr.sin_addr.s_addr = oc->data_dest_addr.addr.ipv4;
} else {
/*
* For now, only the bearer type "GPRS / UTRAN packet service /
@@ -760,6 +907,7 @@ static void stk_open_channel(struct ofono_stk *stk)
memcpy(&stk->bearer_desc, &oc->bearer_desc,
sizeof(struct stk_bearer_description));
+ stk->protocol = oc->uti.protocol;
stk->link_on_demand = (stk->pending_cmd->qualifier &
STK_OPEN_CHANNEL_FLAG_IMMEDIATE) ? FALSE : TRUE;
@@ -848,11 +996,14 @@ static void stk_send_data(struct ofono_stk *stk,
return;
} else {
- /*
- * TODO
- * send the data immediately, flush the tx buffer
- */
- rsp.send_data.tx_avail = stk->tx_buffer.data.len;
+ while (stk->tx_buffer.data.len - stk->tx_buffer.tx_avail) {
+ if (stk_channel_data_write(stk) == 0) {
+ ofono_error("Failed to send data");
+ rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+ goto out;
+ }
+ }
+ rsp.send_data.tx_avail = stk->tx_buffer.tx_avail;
}
out:
--
1.7.1
next prev parent reply other threads:[~2011-05-20 16:26 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-05-20 16:26 [PATCH v4 1/8] stk: Clear 'respond_on_exit' flag after sending the terminal response Philippe Nunes
2011-05-20 16:26 ` [PATCH v4 2/8] stk: Introduce BIP command handlers Philippe Nunes
2011-06-02 0:28 ` Denis Kenzior
2011-06-10 14:03 ` Philippe Nunes
2011-06-08 8:01 ` Denis Kenzior
2011-05-20 16:26 ` [PATCH v4 3/8] gprs: Add 'stk' gprs context type Philippe Nunes
2011-06-01 5:30 ` Denis Kenzior
2011-05-20 16:26 ` [PATCH v4 4/8] gprs: Add private APIs for adding/activating/removing hidden PDP contexts Philippe Nunes
2011-06-01 6:18 ` Denis Kenzior
2011-06-10 9:44 ` Philippe Nunes
2011-06-08 7:46 ` Denis Kenzior
2011-05-20 16:26 ` [PATCH v4 5/8] stk: Use Gprs private APIs to handle the Open channel/Close Channel Philippe Nunes
2011-05-20 16:26 ` [PATCH v4 6/8] gprs: Add a host route for STK context type Philippe Nunes
2011-06-01 6:26 ` Denis Kenzior
2011-05-20 16:26 ` [PATCH v4 7/8] stk: Add support of the Setup event list proactive command Philippe Nunes
2011-05-20 16:26 ` Philippe Nunes [this message]
2011-06-01 5:26 ` [PATCH v4 1/8] stk: Clear 'respond_on_exit' flag after sending the terminal response Denis Kenzior
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1305908781-8322-8-git-send-email-philippe.nunes@linux.intel.com \
--to=philippe.nunes@linux.intel.com \
--cc=ofono@ofono.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox