Ad van der Weiden / sdp

Dependents:   mbed_TANK_Kinect ftusbClass

Revision:
3:e8d2ebb7392e
Parent:
2:d5a27b2d2e08
Child:
4:d5c3e499603d
--- a/sdp.h	Thu Apr 07 21:01:39 2011 +0000
+++ b/sdp.h	Wed May 04 09:27:32 2011 +0000
@@ -1,6 +1,7 @@
 #ifndef SDP_H
 #define SDP_H
 #include "AvailableMemory.h"
+#include "sdp_data.h"
 #include <map>
 #define OFFSET  8
 
@@ -9,13 +10,15 @@
 typedef map<unsigned short, sdp_data*> serv_rec;
 
 void attribHandler(serv_rec *r);
+unsigned parseUUID(const u8* data, int len, unsigned &p);
+unsigned length(const unsigned char *el, unsigned &p);
+unsigned getval(const unsigned char *p, int n) ;
+void errorhandler(unsigned err);//default error handler
 
-//TODO: add support for multiple connections
-//TODO: add server support, now only client
-//at the moment, SDP can handle only one connection at a time
-class SDPManager: public SocketHandler {
-    int _l2cap;
-    int sdp_socket; //at the moment the only socket
+
+class SDPHandler: public SocketHandler {
+//    int _l2cap;
+    int sdp_socket;
     unsigned char l2cap_buf[100+OFFSET];
     unsigned char* buf;
     unsigned txid;
@@ -26,81 +29,27 @@
     sdp_data *tree;//root of the entire service tree
     map<unsigned, serv_rec*> services;//the set of supported services <handle, service>
     map<unsigned, serv_rec*>::iterator index;
+//server properties
+//    static map<unsigned, serv_rec*> server;
+//    static int serverSock;
 public:
-    SDPManager(): _l2cap(0), txid(1), tree(0) {
-        ErrorResponse=errorhandler;
-        ServiceSearchResponse=0;
-        ServiceAttributeResponse=attribHandler;
-        ServiceSearchAttributeResponse=0;
-        buf = l2cap_buf+OFFSET;
-        contBuf = 0;
-        byteCount = 0;
-        contState[0] = 0;
-        _state = 0;
-    }
-
-    void Clear() {
-        for (index = services.begin(); index != services.end(); index++) {//for all services
-            for (serv_rec::iterator it = index->second->begin(); it != index->second->end(); it++)//for all attributes
-                delete it->second; //delete the attribute value tree
-            delete (*index).second; //delete the attribute list
-        }
-        services.clear();//and empty the services list
+    SDPHandler();
+    void Clear();
+    virtual int Open(SocketInternal* sock, SocketAddrHdr* addr);
+//    virtual int Accept(SocketInternal *sock, int scid, int rxid); //called indirectly from BTDevice::Control
+    virtual int Send(SocketInternal* sock, const u8* data, int len);
+    virtual int Close(SocketInternal* sock);
+    virtual char* Name() {
+        return "SDPHandler SocketHandler";
     }
-
-    //Called as: Socket_Open(SOCKET_SDP, addr, callback, userdata(this))
-    virtual int Open(SocketInternal* sock, SocketAddrHdr* addr) {
-        L2CAPAddr* ad = (L2CAPAddr*)addr;
-        if (_l2cap) {
-            printf("This SDP supports only one connection at a time\n");
-            return 0;
-        }
-        //BD_ADDR* a = &ad->bdaddr;
-        sdp_socket = sock->ID;
-        ad->psm = L2CAP_PSM_SDP;//open the l2cap channel
-        _l2cap = Socket_Open(SOCKET_L2CAP, addr, OnSdpRsp, this);//this is the socket between SDP and the L2CAP layer
-        if (_l2cap <= 0) {
-            printf("Opening L2CAP channel failed\n");
-            return _l2cap;
-        }
-        printf("Successfully opened L2CAP channel for SDP on socket %d\n", _l2cap);
-        return sock->ID;
-    }
-
-    virtual int Send(SocketInternal* sock, const u8* data, int len) {
-        printf("SDPManager::Send should not be called directly\n");
-        return Socket_Send(_l2cap, data, len);
-    }
-
-    virtual int Close(SocketInternal* sock) {
-        Clear();
-        printf("SDP socket %d and L2CAP socket %d closed, freemem=%d\n", sock->ID, _l2cap, AvailableMemory(1));
-        int retval = Socket_Close(_l2cap);//could also keep it open for the next connection
-        _l2cap = 0;
-        return retval;
-    }
-
-    virtual char* Name() {
-        return "SDPManager SocketHandler";
-    }
-
     void OnSdpRsp(const u8* data, int len);
-    //this function is called when the L2CAP layer receives SDP packets (see SDPManager::Open), userdata is the sdpmanager instance
-    static void OnSdpRsp(int socket, SocketState state, const u8* data, int len, void* userData) {
-        printf("\x1B[%dm", 35);
-//        printf("OnSdpRsp(socket=%d, state=%d, len=%d)\n", socket, state, len);
-        printf("OnSdpRsp(socket=%d, state=%d, len=%d, freemem=%d\n", socket, state, len, AvailableMemory(1));
-        SDPManager *self = (SDPManager*)userData;
-        if (state == SocketState_Open) {
-            self->OnSdpRsp(data, len);
-        }
-        printf("\x1B[%dm", 0);
-    }
+    static void OnSdpRsp(int socket, SocketState state, const u8* data, int len, void* userData);
 
     //this function is called when the SDP sockets receives data (see HCICallback in TestShell),
     //currently does not happen because not forwarded from OnSdpRsp, can be used to handle multiple connections
     static void OnSockCallback(int socket, SocketState state, const u8* data, int len, void* userData) ;
-    static void errorhandler(unsigned err);
+    //The SDP server is stateless hence can be static
+//    static void SDPServer(int socket, SocketState state, const u8* data, int len, void* userData) ;
 
     void (*ErrorResponse)(unsigned) ;
     void (*ServiceSearchResponse)() ;
@@ -109,14 +58,127 @@
     int ServiceSearchRequest(sdp_data *sp, unsigned count, unsigned cs=0);
     int ServiceAttributeRequest(unsigned handle, unsigned count, sdp_data* al, unsigned cs=0) ;
     int ServiceSearchAttributeRequest(sdp_data *sp, unsigned count, sdp_data* al, unsigned cs=0);
+//server
+//    static int ServiceSearchAttributeReply(unsigned rxid, sdp_data* al, unsigned count, unsigned cs=0);
 private:
-    unsigned length(const unsigned char *el, unsigned &p);
-    unsigned getval(const unsigned char *p, int n) ;
+//    static unsigned length(const unsigned char *el, unsigned &p);
+//    static unsigned getval(const unsigned char *p, int n) ;
+//    static unsigned parseUUID(const u8* data, int len, unsigned &p);
     unsigned parse (const unsigned char *el, unsigned count, sdp_data* &result, serv_rec* &record) ;
     unsigned parseLight (const unsigned char *el, unsigned count, sdp_data* &result, serv_rec* &record) ;
     int parseRsp(const unsigned char*rsp, int len) ;
     void append(const unsigned char*rsp, int len) ;
     void freeBuf();
 };
+/*
+class SDPClient: public SDPHandler {
+};
+
+class SDPServer: public SDPHandler {
+};
+*/
+class SDPManager: public SocketHandler {
+    map<int, SDPHandler*> handlers;
+//server properties
+//    SDPHandler *Server;
+    static map<unsigned, serv_rec*> server;
+    static int serverSock;
+    bool once;
+public:
+    SDPManager() {
+        once = true;
+    }
+    virtual int Open(SocketInternal* sock, SocketAddrHdr* addr) {
+        printf("SDPManager::Open(sock (ID=%d, type=%d), addr): should not be called\n", sock->ID, sock->Type);
+        return sock->ID;//((SDPHandler*)sock->userData)->Open(sock, addr);
+    }
+    int Open(SocketAddrHdr* addr) {
+        L2CAPAddr* ad = (L2CAPAddr*)addr;
+        ad->psm = L2CAP_PSM_SDP;//open the l2cap channel
+        SDPHandler *h = new SDPHandler;
+        int s = Socket_Open(SOCKET_L2CAP, addr, &SDPHandler::OnSdpRsp, h);
+        handlers[s] = h;
+        return s;
+    }
+    virtual int Accept(SocketInternal *sock, int scid, int rxid) { //called indirectly from BTDevice::Control
+        if (once) {
+            once = false;
+            buildServer();//build the DB on the first connection
+        }
+        //sock is registered as an SDP sock but we use it as an L2CAP sock
+        //type=SDP
+        //userData = BTDevice
+        //Internal = L2CAPSocket
+        BTDevice *l2cap = (BTDevice*)sock->userData;
+        //sock->dcid = scid
+        //sock->scid = something based on sock->ID
+        serverSock = sock->ID;
+        printf("Invoking accept on %p (%s) for sock %d and scid=%d\n", l2cap, l2cap->Name(), sock->ID, scid);
+        return l2cap->Accept(sock, scid, rxid);
+    }
+    virtual int Send(SocketInternal* sock, const u8* data, int len) {//called by the server
+        BTDevice *l2cap = (BTDevice*)sock->userData;
+        return l2cap->Send(sock, data, len);
+    }
+    virtual int Close(SocketInternal* sock) {
+        printf("SDPManager::Close() closing  socket %d\n", sock->ID);
+        SDPHandler *h = handlers[sock->ID];
+        int retval = h->Close(sock);
+        delete h;
+        handlers[sock->ID] = 0;
+        return retval;
+    }
+    void Destroy(int s) {
+        printf("Deleting handler for socket %d\n", s);
+        delete handlers[s];
+        handlers[s] = 0;
+    }
+    virtual char* Name() {
+        return "SDPManager SocketHandler";
+    }
+    //void OnSdpRsp(const u8* data, int len);
+    static void OnSdpRsp(int socket, SocketState state, const u8* data, int len, void* userData) {
+        printf("SDPManager::OnSdpRsp(socket %d, state %d, len %d)\n", socket, state, len);
+    }
+    //The SDP server is (almost) stateless hence can be static
+    static void SDPServer(int socket, SocketState state, const u8* data, int len, void* userData) ;
+    static void match(bool elig[], unsigned uuid);
+    static bool isInList(unsigned short id, const unsigned char* list, int end);
+    static void addToReply(sdp_data *svc, serv_rec *list, const unsigned char* att, int end);
+    static int findUUID(unsigned h, unsigned uuid);
+    void buildServer();
+    static int ServiceSearchAttributeReply(unsigned rxid, sdp_data* al, unsigned count, unsigned cs=0);
+    /*
+        //this function is called when the SDP sockets receives data (see HCICallback in TestShell),
+        //currently does not happen because not forwarded from OnSdpRsp, can be used to handle multiple connections
+        static void OnSockCallback(int socket, SocketState state, const u8* data, int len, void* userData) ;
+
+        static void errorhandler(unsigned err);
+
+        void (*ErrorResponse)(unsigned) ;
+        void (*ServiceSearchResponse)() ;
+        void (*ServiceAttributeResponse)(serv_rec*) ;
+        void (*ServiceSearchAttributeResponse)() ;
+        int ServiceSearchRequest(sdp_data *sp, unsigned count, unsigned cs=0);
+        int ServiceAttributeRequest(unsigned handle, unsigned count, sdp_data* al, unsigned cs=0) ;
+        int ServiceSearchAttributeRequest(sdp_data *sp, unsigned count, sdp_data* al, unsigned cs=0);
+    //server
+    private:
+        static unsigned length(const unsigned char *el, unsigned &p);
+        static unsigned getval(const unsigned char *p, int n) ;
+        static unsigned parseUUID(const u8* data, int len, unsigned &p);
+        static void addAttrib(unsigned h, unsigned short id, sdp_data *attrib);
+        static void addIndex(unsigned h, unsigned uuid);
+        static int findUUID(unsigned h, unsigned uuid);
+        static void match(bool elig[], unsigned uuid);
+        static bool isInList(unsigned short id, const unsigned char* list, int end);
+        void buildServer();
+        unsigned parse (const unsigned char *el, unsigned count, sdp_data* &result, serv_rec* &record) ;
+        unsigned parseLight (const unsigned char *el, unsigned count, sdp_data* &result, serv_rec* &record) ;
+        int parseRsp(const unsigned char*rsp, int len) ;
+        void append(const unsigned char*rsp, int len) ;
+        void freeBuf();
+    */
+};
 
 #endif
\ No newline at end of file