---
 src/stk.c |  154 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 154 insertions(+), 0 deletions(-)

diff --git a/src/stk.c b/src/stk.c
index 8d4f7c0..1e4d237 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -28,6 +28,9 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <unistd.h>
 
 #include <glib.h>
 #include <gdbus.h>
@@ -88,6 +91,9 @@ struct ofono_stk {
                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;
        } bip;
 };
 
@@ -582,10 +588,152 @@ static void stk_alpha_id_unset(struct ofono_stk *stk)
        stk_agent_request_cancel(stk->current_agent);
 }
 
+static gboolean receive_callback(GIOChannel *channel, GIOCondition cond,
+                               gpointer userdata)
+{
+       return TRUE;
+}
+
 static void ofono_stk_activate_context_cb(int error, const char *interface,
                                                const char *ip,
                                                void *data)
 {
+       struct ofono_stk *stk = data;
+       struct stk_response rsp;
+       struct ofono_error failure = { .type = OFONO_ERROR_TYPE_FAILURE };
+       GIOChannel *io;
+       int sk;
+
+       DBG("");
+
+       memset(&rsp, 0, sizeof(rsp));
+       rsp.result.type = STK_RESULT_TYPE_SUCCESS;
+
+       if (error < 0) {
+               ofono_error("Failed to connect gprs context");
+
+               if (stk->pending_cmd == NULL ||
+                               (stk->pending_cmd->type !=
+                               STK_COMMAND_TYPE_OPEN_CHANNEL &&
+                               stk->pending_cmd->type !=
+                               STK_COMMAND_TYPE_SEND_DATA)) {
+                       /* TODO send channel status event */
+                       return;
+               } else {
+                       rsp.result.type = STK_RESULT_TYPE_NETWORK_UNAVAILABLE;
+                       goto out;
+               }
+       } else {
+               DBG("Interface %s, IP = %s", interface, ip);
+               stk->bip.channel.status =
+                               STK_CHANNEL_PACKET_DATA_SERVICE_ACTIVATED;
+       }
+
+       if (stk->bip.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->bip.dest_addr,
+                                               sizeof(stk->bip.dest_addr));
+
+               if (error < 0) {
+                       close(sk);
+                       rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+                       goto out;
+               }
+       } else if (stk->bip.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 = socket(AF_INET, SOCK_RAW, 0);
+               if (sk < 0) {
+                       rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+                       goto out;
+               }
+
+               /* Bind socket to specified interface */
+               if (interface) {
+                       struct ifreq ifreq;
+
+                       memset(&ifreq, 0, sizeof(ifreq));
+                       strcpy(ifreq.ifr_name, interface);
+                       error = setsockopt(sk, SOL_SOCKET,
+                                       SO_BINDTODEVICE, &ifreq, sizeof(ifreq));
+                       if (error < 0) {
+                               ofono_error("Failed to bind socket "
+                                               "to interface");
+                               close(sk);
+                               rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+                               goto out;
+                       }
+               }
+       }
+
+       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, 0, NULL);
+       g_io_channel_set_encoding(io, NULL, NULL);
+       g_io_channel_set_buffered(io, FALSE);
+
+       stk->bip.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->bip.io = io;
+       g_io_channel_unref(io);
+
+       if (stk->pending_cmd == NULL) {
+               /* TODO send channel status event */
+               return;
+       } else if (stk->pending_cmd->type == STK_COMMAND_TYPE_OPEN_CHANNEL) {
+               rsp.open_channel.channel.id = stk->bip.channel.id;
+               rsp.open_channel.channel.status = stk->bip.channel.status;
+               rsp.open_channel.buf_size = stk->bip.tx_avail;
+               memcpy(&rsp.open_channel.bearer_desc, &stk->bip.bearer_desc,
+                               sizeof(struct stk_bearer_description));
+       } else if (stk->pending_cmd->type == STK_COMMAND_TYPE_SEND_DATA &&
+                       stk->bip.link_on_demand) {
+               /* TODO send data */
+               rsp.send_data.tx_avail = stk->bip.tx_avail;
+       } else {
+               /* TODO send channel status event */
+               return;
+       }
+
+out:
+       if (stk_respond(stk, &rsp, stk_command_cb))
+               stk_command_cb(&failure, stk);
+
+       if (rsp.result.type != STK_RESULT_TYPE_SUCCESS)
+               stk_close_channel(stk);
 }
 
 static void stk_open_channel(struct ofono_stk *stk)
@@ -611,6 +759,12 @@ static void stk_open_channel(struct ofono_stk *stk)
                 */
                rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
                goto out;
+       } else if (oc->data_dest_addr.type == STK_ADDRESS_IPV4) {
+               memset(&stk->bip.dest_addr, 0, sizeof(stk->bip.dest_addr));
+               stk->bip.dest_addr.sin_family = AF_INET;
+               stk->bip.dest_addr.sin_port = htons(oc->uti.port);
+               stk->bip.dest_addr.sin_addr.s_addr
+                                               = oc->data_dest_addr.addr.ipv4;
        }
 
        stk->bip.channel.id = DEFAULT_CHANNEL_ID;
-- 
1.7.1

_______________________________________________
ofono mailing list
[email protected]
http://lists.ofono.org/listinfo/ofono

Reply via email to