summaryrefslogtreecommitdiff
path: root/src/syncevo/ObexTransportAgent.h
blob: c6fdae8cb81c8f01c85b34d2f3efbc2d9897edc4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
/*
 * Copyright (C) 2009 Intel Corporation
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) version 3.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

#ifndef INCL_OBEXTRANSPORTAGENT
#define INCL_OBEXTRANSPORTAGENT

#include <config.h>

#ifdef ENABLE_OBEX

#include <syncevo/TransportAgent.h>
#include <syncevo/Logging.h>
#include <syncevo/declarations.h>
#include <syncevo/SmartPtr.h>

#ifdef  ENABLE_BLUETOOTH
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>
#endif
#include <openobex/obex.h>

SE_BEGIN_CXX

/**
 * utility class for various enties stored by
 * ObexTransportAgent in SmartPtr
 */
class ObexUnref {
 public:
    static void unref(GMainContext *context) { g_main_context_unref(context); }
    static void unref(sdp_session_t *sdp) { sdp_close(sdp); }
    static void unref(GIOChannel *channel) { g_io_channel_unref(channel); }
    static void unref(obex_t *handle) { OBEX_Cleanup(handle); }
};

typedef eptr<GMainContext, GMainContext, ObexUnref> GMainContextPtr;
typedef eptr<sdp_session_t, sdp_session_t, ObexUnref> SDPSessionPtr;
typedef eptr<GIOChannel, GIOChannel, ObexUnref> GIOChannelPtr;
typedef eptr<obex_t, obex_t, ObexUnref> ObexPtr;

class Socket {
    int socketfd;
 public:
     Socket() {socketfd = -1;}
     Socket(int fd) {socketfd = fd;}
     ~Socket() { if (socketfd !=-1) {::close (socketfd);} }
     int get() {return socketfd;}
};



/**
 * message send/receive with libopenobex
 * should work with a transport binding (Bluetooth, USB, etc.)
 */
class ObexTransportAgent : public TransportAgent 
{
    public:
        enum OBEX_TRANS_TYPE{
            OBEX_BLUETOOTH,
            OBEX_USB,
            INVALID
        };

        /**
         * @param loop     the glib loop to use when waiting for IO;
         *                 transport will increase the reference count;
         *                 if NULL a new loop in the default context is used
         */
        ObexTransportAgent(OBEX_TRANS_TYPE type, GMainLoop *loop);
        ~ObexTransportAgent();

        virtual void setURL (const std::string &url);
        virtual void setContentType(const std::string &type);
        virtual void shutdown();
        virtual void send(const char *data, size_t len);
        virtual void cancel();
        virtual Status wait(bool noReply);
        virtual void getReply(const char *&data, size_t &len, std::string &contentType);
        virtual void setTimeout(int seconds);
        /* Obex specific api: connecting the underlying transport */
        void connect();

    private:
        /*call back used by libopenobex, will route to member function obex_callback*/
        static void obex_event (obex_t *handle, obex_object_t *object, int mode, int event, int obex_cmd, int obex_rsp);
        /* callback used by obex fd poll, will route to member function
         * obex_fd_source_cb_impl */
        static gboolean obex_fd_source_cb (GIOChannel *io, GIOCondition cond, void *udata);
        /* callback used by Bluetooth sdp poll, will route to member function
         * sdp_source_cb_impl */
        static gboolean sdp_source_cb (GIOChannel *io, GIOCondition cond, void *udata);
        /* callback called when a sdp async transaction is finished, route to
         * member function sdp_callback_impl*/
        static void sdp_callback (uint8_t type, uint16_t status, uint8_t *rsp, size_t size, void *user_data);

        void obex_callback (obex_object_t *object, int mode, int event, int obex_cmd, int obex_rsp);
        gboolean obex_fd_source_cb_impl (GIOChannel *io, GIOCondition cond);
        gboolean sdp_source_cb_impl (GIOChannel *io, GIOCondition cond);
        void sdp_callback_impl (uint8_t type, uint16_t status, uint8_t *rsp, size_t size);

        /**
         * Handle exception thrown by any of the C callbacks.
         * Exception must not escape into calling C function.
         * Instead, set bad status and wait for that to
         * be discovered in wait().
         */
        void handleException(const char *where);

        /* First phase of OBEX connect: connect to remote peer */
        void connectInit ();
        /* Second phase of OBEX connect: send connect cmd to initalize */
        void connectReq ();

        /* wrapper of OBEX_ObjectNew*/
        obex_object_t * newCmd (uint8_t cmd);

        static const int DEFAULT_RX_MTU=32767;
        static const int DEFAULT_TX_MTU=32767;

        /*Indicates when the OBEX transport has finished it's part of working,
         * it's the application to turn to do something */
        bool m_obexReady;
        Status m_status;

        /*
         * The underlying transport type: Bluetooth, USB.
         */
        OBEX_TRANS_TYPE m_transType;

        /** context that needs to be kept alive while waiting for OBEX */
        GMainContextPtr m_context;

        /* The address of the remote device  
         * macadd for Bluetooth; device name for usb; host name for
         * tcp/ip
         */
        std::string m_address;
        /*
         * Service port for the remote device 
         * channel for Bluetooth, port for tcp/ip
         */
        int m_port;

        /*The underlying socket fd*/
        cxxptr<Socket> m_sock;
        GLibEvent m_obexEvent;
        GIOChannelPtr m_channel;

        std::string m_contentType;
        arrayptr<char> m_buffer;
        int m_bufferSize;

        SDPSessionPtr m_sdp;
        GLibEvent m_sdpEvent;

        int m_timeoutSeconds;
        time_t m_requestStart;
        /** OBEX poll interval */
        static const int OBEX_POLL_INTERVAL = 1;

        uint32_t m_connectId;
        //already fired disconnect
        bool m_disconnecting;

        ObexPtr m_handle;
        enum CONNECT_STATUS {
            START, 
            SDP_START, //sdp transaction start
            SDP_REQ, //sdp request has been sent
            SDP_DONE, //sdp transaction finished
            ADDR_READY, //address is prepared
            INIT0,  //connect is called but not finished
            INIT1,  //connect is finished. 
            INIT2,  //connect cmd is sent, but not finished.
            CONNECTED, //connection sucessfully setup
            ERROR,  //connection in error state
            END
        };
        CONNECT_STATUS m_connectStatus;
};

SE_END_CXX
#endif //ENABLE_OBEX
#endif