From 4f884115bab6335a3302d3b1f83f27ec09dfec21 Mon Sep 17 00:00:00 2001
From: phil <me@filou.se>
Date: Tue, 20 Apr 2021 12:26:16 +0200
Subject: [PATCH] minor fixes and temp commit

---
 src/include/aes67/utils/rtsp-srv.h  |  13 +-
 src/utils/rav-publish/rav-publish.c | 298 +++++++++++++++-------------
 src/utils/rtsp-srv.c                | 167 ++++++++++++++--
 3 files changed, 320 insertions(+), 158 deletions(-)

diff --git a/src/include/aes67/utils/rtsp-srv.h b/src/include/aes67/utils/rtsp-srv.h
index e60ff55..f06f060 100644
--- a/src/include/aes67/utils/rtsp-srv.h
+++ b/src/include/aes67/utils/rtsp-srv.h
@@ -50,6 +50,7 @@ enum aes67_rtsp_srv_state {
     aes67_rtsp_srv_state_init = 0,
     aes67_rtsp_srv_state_listening,
     aes67_rtsp_srv_state_receiving,
+    aes67_rtsp_srv_state_processing,
     aes67_rtsp_srv_state_sending
 };
 
@@ -98,6 +99,8 @@ struct aes67_rtsp_srv {
     struct sockaddr_in client_addr;
     int client_sockfd;
 
+    bool blocking;
+
     struct aes67_rtsp_srv_resource * first_res;
 
 
@@ -117,8 +120,8 @@ struct aes67_rtsp_srv {
             u16_t minor;
         } version;
         enum aes67_rtsp_srv_method method;
-//    char * uri;
-//    u8_t urilen;
+        u8_t * uri;
+        u8_t urilen;
         u16_t header_len;
         u16_t content_length;
 
@@ -130,7 +133,7 @@ struct aes67_rtsp_srv {
         u16_t status_code;
         u16_t sent;
         u16_t len;
-        u8_t data[AES67_RTSP_SRV_TXBUFSIZE]
+        u8_t data[AES67_RTSP_SRV_TXBUFSIZE];
     } res; // response
 };
 
@@ -140,12 +143,14 @@ void aes67_rtsp_srv_deinit(struct aes67_rtsp_srv * srv);
 int aes67_rtsp_srv_start(struct aes67_rtsp_srv * srv, const enum aes67_net_ipver ipver, const u8_t *ip, u16_t port);
 void aes67_rtsp_srv_stop(struct aes67_rtsp_srv * srv);
 
+void aes67_rtsp_srv_blocking(struct aes67_rtsp_srv * srv, bool blocking);
+
 void aes67_rtsp_srv_process(struct aes67_rtsp_srv * srv);
 
 void aes67_rtsp_srv_sdp_getter(struct aes67_rtsp_srv * srv, void * sdpref, u8_t * buf, u16_t * len, u16_t maxlen);
 void aes67_rtsp_srv_http_handler(struct aes67_rtsp_srv * srv, const enum aes67_rtsp_srv_method method, const char * uri, const u8_t urilen, u8_t * buf, u16_t * len, u16_t maxlen, void * response_data);
 
-struct aes67_rtsp_srv_resource * aes67_rtsp_srv_sdp_add(struct aes67_rtsp_srv * srv, const char * uri, const u8_t urilen, const void * sdpref);
+struct aes67_rtsp_srv_resource * aes67_rtsp_srv_sdp_add(struct aes67_rtsp_srv * srv, const char * uri, const u8_t urilen, void * sdpref);
 void aes67_rtsp_srv_sdp_remove(struct aes67_rtsp_srv * srv, void * sdpref);
 
 
diff --git a/src/utils/rav-publish/rav-publish.c b/src/utils/rav-publish/rav-publish.c
index df0dff3..30f5659 100644
--- a/src/utils/rav-publish/rav-publish.c
+++ b/src/utils/rav-publish/rav-publish.c
@@ -18,6 +18,7 @@
 
 #include "aes67/utils/mdns.h"
 #include "aes67/rav.h"
+#include "aes67/utils/rtsp-srv.h"
 #include "dnmfarrell/URI-Encode-C/src/uri_encode.h"
 #include "aes67/net.h"
 #include "aes67/sdp.h"
@@ -65,9 +66,7 @@ static struct {
 
 static volatile bool keep_running;
 
-static struct {
-    int sockfd;
-} rtsp;
+static struct aes67_rtsp_srv rtsp_srv;
 
 static aes67_mdns_context_t mdns;
 
@@ -107,95 +106,187 @@ static void publish_callback(aes67_mdns_resource_t res, enum aes67_mdns_result r
     }
 }
 
-static void fd_blocking(int fd, bool yes){
+//static void fd_blocking(int fd, bool yes){
+//
+//    // set non-blocking
+//    int flags = fcntl(fd, F_GETFL, 0);
+//    flags = (flags & ~O_NONBLOCK) | (yes ? 0 : O_NONBLOCK);
+//    if (fcntl(fd, F_SETFL, flags) == -1){
+//        perror("fcntl()");
+//        close(fd);
+//        exit(EXIT_FAILURE);
+//    }
+//}
+
+static void block_until_event(){
+
+    int nfds;
+    fd_set rfds, xfds;
+//    sigset_t sigmask;
+
+    FD_ZERO(&rfds);
+    FD_ZERO(&xfds);
+
+    if (opts.rtsp){
+        nfds = rtsp_srv.listen_sockfd;
+        FD_SET(rtsp_srv.listen_sockfd, &rfds);
+        FD_SET(rtsp_srv.listen_sockfd, &xfds);
+        if (rtsp_srv.client_sockfd != -1){
+            FD_SET(rtsp_srv.client_sockfd, &rfds);
+            FD_SET(rtsp_srv.client_sockfd, &xfds);
+            if (rtsp_srv.client_sockfd > rtsp_srv.listen_sockfd){
+                nfds = rtsp_srv.client_sockfd;
+            }
+        }
+    }
 
-    // set non-blocking
-    int flags = fcntl(fd, F_GETFL, 0);
-    flags = (flags & ~O_NONBLOCK) | (yes ? 0 : O_NONBLOCK);
-    if (fcntl(fd, F_SETFL, flags) == -1){
-        perror("fcntl()");
-        close(fd);
-        exit(EXIT_FAILURE);
+    int * sockfds;
+    size_t count = 0;
+    aes67_mdns_getsockfds(mdns, &sockfds, &count);
+    for (size_t i = 0; i < count; i++) {
+        FD_SET(sockfds[i], &rfds);
+        FD_SET(sockfds[i], &xfds);
+        if (sockfds[i] > nfds) {
+            nfds = sockfds[i];
+        }
     }
+
+    nfds++;
+
+    // just wait until something interesting happens
+    select(nfds, &rfds, NULL, &xfds, NULL);
 }
 
-static int rtsp_setup()
+static int mdns_setup()
 {
-    rtsp.sockfd = socket(AF_INET, SOCK_STREAM, 0);
-    if (rtsp.sockfd == -1){
-        perror("socket()");
-        return EXIT_FAILURE;
-    }
 
-    struct sockaddr_in addr;
+    mdns = aes67_mdns_new();
 
-    addr.sin_family = AF_INET;
-    addr.sin_port = htons(opts.port);
-    addr.sin_addr.s_addr = INADDR_ANY;
+    sdpres_t * sdpres = first_sdpres;
+    while(sdpres != NULL){
 
-    if (bind(rtsp.sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) == -1){
-        perror("bind()");
-        close(rtsp.sockfd);
-        rtsp.sockfd = - 1;
-        return EXIT_FAILURE;
-    }
+        aes67_mdns_resource_t service = aes67_mdns_service_start(mdns, AES67_RAV_MDNS_SESSION, sdpres->name,
+                                                                 NULL, opts.host, opts.port, 0, NULL, publish_callback, NULL);
 
-    if (listen(rtsp.sockfd, 10) == -1){
-        close(rtsp.sockfd);
-        rtsp.sockfd = -1;
-        perror ("listen()");
-        return EXIT_FAILURE;
-    }
+        if (service == NULL){
+            fprintf(stderr, "failed to create service\n");
+            return EXIT_FAILURE;
+        }
+
+        if (opts.host != NULL){
 
-    fd_blocking(rtsp.sockfd, false);
+            struct aes67_net_addr * addr = opts.addr.ipver == aes67_net_ipver_undefined ? &sdpres->addr : &opts.addr;
 
-    return EXIT_SUCCESS;
-}
+            u16_t rrtype;
+            u16_t rdlen;
+            u8_t * rdata;
 
-static void rtsp_teardown() {
-    if (!opts.rtsp || rtsp.sockfd == -1) {
-        return;
+            if (addr->ipver == aes67_net_ipver_4){
+                rrtype = 1;
+                rdlen = 4;
+            } else { // ipver6
+                rrtype = 28;
+                rdlen = 16;
+            }
+            rdata = addr->ip;
+
+            if (aes67_mdns_service_addrecord(mdns, service, rrtype, rdlen, rdata, opts.ttl) == NULL){
+                fprintf(stderr, "failed to add A/AAAA record\n");
+                return EXIT_FAILURE;
+            }
+
+            if (aes67_mdns_service_commit(mdns, service) == NULL){
+                fprintf(stderr, "error committing service\n");
+                return EXIT_FAILURE;
+            }
+
+        }
+
+        sdpres = sdpres->next;
     }
 
-    close(rtsp.sockfd);
-    rtsp.sockfd = -1;
+    return EXIT_SUCCESS;
+}
 
+static void mdns_teardown()
+{
+    if (mdns) {
+        aes67_mdns_delete(mdns);
+    }
+}
 
+static void mdns_process()
+{
+    aes67_mdns_process(mdns, 0);
 }
 
-static void rtsp_process()
+static int rtsp_setup()
 {
-    static int sockfd = -1;
+    aes67_rtsp_srv_init(&rtsp_srv, false, NULL);
 
-    if (sockfd == -1){
-        struct sockaddr_in addr;
-        socklen_t socklen;
+    aes67_rtsp_srv_blocking(&rtsp_srv, false);
 
-        memset(&addr, 0, sizeof(struct sockaddr_in));
+    sdpres_t * sdpres = first_sdpres;
+    while(sdpres != NULL){
 
-        if ((sockfd = accept(rtsp.sockfd, (struct sockaddr *)&addr, &socklen)) != -1) {
+        char uri[256];
+        u16_t urilen = sizeof("/by-name");
 
-            fd_blocking(sockfd, true);
+        memcpy(uri, "/by-name/", sizeof("/by-name"));
 
-            u8_t ip[4];
-            *(u32_t*)ip = addr.sin_addr.s_addr;
-            u16_t port = ntohs(addr.sin_port);
+        urilen += uri_encode(sdpres->name, strlen(sdpres->name), &uri[urilen], sizeof(uri) - urilen - 1);
 
-            printf("Connected! from %d.%d.%d.%d:%hu\n", ip[0], ip[1], ip[2], ip[3], port);
+        uri[urilen] = '\0';
 
-            u8_t buf[1024];
+        printf("final uri [%d]: [%s]\n", urilen, uri);
 
-            ssize_t rlen = read(sockfd, buf, sizeof(buf));
+        aes67_rtsp_srv_sdp_add(&rtsp_srv, uri, urilen, sdpres);
 
-            if (rlen > 0){
-                buf[rlen] = '\0';
-                printf("%s\n", buf);
-            }
+        sdpres = sdpres->next;
+    }
 
-            close(sockfd);
-            sockfd = -1;
-        }
+    if (aes67_rtsp_srv_start(&rtsp_srv, opts.addr.ipver, opts.addr.ip, opts.port)){
+        fprintf(stderr, "failed to start rtsp server\n");
+        return EXIT_FAILURE;
+    }
+
+    return EXIT_SUCCESS;
+}
+
+static void rtsp_teardown()
+{
+    if (!opts.rtsp) {
+        return;
     }
+
+    aes67_rtsp_srv_deinit(&rtsp_srv);
+}
+
+static void rtsp_process()
+{
+    aes67_rtsp_srv_process(&rtsp_srv);
+}
+
+void aes67_rtsp_srv_sdp_getter(struct aes67_rtsp_srv * srv, void * sdpref, u8_t * buf, u16_t * len, u16_t maxlen)
+{
+    assert(srv);
+    assert(sdpref);
+    assert(buf);
+    assert(len);
+    assert(maxlen);
+
+    sdpres_t * sdpres = sdpref;
+
+    fprintf(stderr, "serving rtsp describe for uri %s\n", sdpres->name);
+
+    if (maxlen < sdpres->len){
+        fprintf(stderr, "sdp file too big for compiled in buffer size");
+        *len = 0;
+        return;
+    }
+
+    memcpy(buf, sdpres->data, sdpres->len);
+    *len += sdpres->len;
 }
 
 static int load_sdpres(char * fname, size_t maxlen)
@@ -213,7 +304,7 @@ static int load_sdpres(char * fname, size_t maxlen)
     }
 
     if (st.st_size > maxlen){
-        fprintf(stderr, "ERROR file too big (%ld bytes, max %zu) %s\n", st.st_size, maxlen, fname);
+        fprintf(stderr, "ERROR file too big (%lld bytes, max %zu) %s\n", st.st_size, maxlen, fname);
         return EXIT_FAILURE;
     }
 
@@ -389,50 +480,9 @@ int main(int argc, char * argv[])
     }
 
 
-    mdns = aes67_mdns_new();
-
-
-    sdpres_t * sdpres = first_sdpres;
-    while(sdpres != NULL){
-
-        aes67_mdns_resource_t service = aes67_mdns_service_start(mdns, AES67_RAV_MDNS_SESSION, sdpres->name,
-                                                                 NULL, opts.host, opts.port, 0, NULL, publish_callback, NULL);
-
-        if (service == NULL){
-            fprintf(stderr, "failed to create service\n");
-            goto shutdown;
-        }
-
-        if (opts.host != NULL){
-
-            struct aes67_net_addr * addr = opts.addr.ipver == aes67_net_ipver_undefined ? &sdpres->addr : &opts.addr;
-
-            u16_t rrtype;
-            u16_t rdlen;
-            u8_t * rdata;
-
-            if (addr->ipver == aes67_net_ipver_4){
-                rrtype = 1;
-                rdlen = 4;
-            } else { // ipver6
-                rrtype = 28;
-                rdlen = 16;
-            }
-            rdata = addr->ip;
-
-            if (aes67_mdns_service_addrecord(mdns, service, rrtype, rdlen, rdata, opts.ttl) == NULL){
-                fprintf(stderr, "failed to add A/AAAA record\n");
-                goto shutdown;
-            }
-
-            if (aes67_mdns_service_commit(mdns, service) == NULL){
-                fprintf(stderr, "error committing service\n");
-                goto shutdown;
-            }
-
-        }
-
-        sdpres = sdpres->next;
+    if (mdns_setup()){
+        fprintf(stderr, "failed mdns setup\n");
+        goto shutdown;
     }
 
 
@@ -442,43 +492,15 @@ int main(int argc, char * argv[])
     keep_running = true;
     while(keep_running){
 
-        int nfds = rtsp.sockfd;
-        fd_set rfds, xfds;
-//    sigset_t sigmask;
-
-        FD_ZERO(&rfds);
-        FD_ZERO(&xfds);
-
-        // set all AF_LOCAL sockets
-        FD_SET(rtsp.sockfd, &rfds);
-        FD_SET(rtsp.sockfd, &xfds);
-
-        int * sockfds;
-        size_t count = 0;
-        aes67_mdns_getsockfds(mdns, &sockfds, &count);
-        for (size_t i = 0; i < count; i++) {
-            FD_SET(sockfds[i], &rfds);
-            FD_SET(sockfds[i], &xfds);
-            if (sockfds[i] > nfds) {
-                nfds = sockfds[i];
-            }
-        }
-
-        nfds++;
-
-        // just wait until something interesting happens
-        select(nfds, &rfds, NULL, &xfds, NULL);
-
-        aes67_mdns_process(mdns, 0);
+        block_until_event();
 
+        mdns_process();
         rtsp_process();
     }
 
 shutdown:
 
-    if (mdns) {
-        aes67_mdns_delete(mdns);
-    }
+    mdns_teardown();
 
     rtsp_teardown();
 
diff --git a/src/utils/rtsp-srv.c b/src/utils/rtsp-srv.c
index eb678d3..554c540 100644
--- a/src/utils/rtsp-srv.c
+++ b/src/utils/rtsp-srv.c
@@ -29,15 +29,36 @@
 #include <fcntl.h>
 #include <syslog.h>
 
-static int sock_nonblock(int sockfd){
+static int sock_set_blocking(int sockfd, bool blocking){
     // set non-blocking
     int flags = fcntl(sockfd, F_GETFL, 0);
-    if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) == -1){
+    flags = (flags & ~O_NONBLOCK ) | (blocking ? 0 : O_NONBLOCK);
+    if (fcntl(sockfd, F_SETFL, flags) == -1){
         return EXIT_FAILURE;
     }
     return EXIT_SUCCESS;
 }
 
+static struct aes67_rtsp_srv_resource * rtsp_resource_by_uri(struct aes67_rtsp_srv * srv, const char * uri, u8_t urilen)
+{
+    assert(srv);
+    assert(uri);
+    assert(urilen);
+
+    struct aes67_rtsp_srv_resource * res = srv->first_res;
+
+    while(res != NULL){
+
+        if (res->urilen == urilen && aes67_memcmp(res->uri, uri, urilen) == 0){
+            return res;
+        }
+
+        res = res->next;
+    }
+
+    return NULL;
+}
+
 void aes67_rtsp_srv_init(struct aes67_rtsp_srv * srv, bool http_enabled, void * user_data)
 {
     assert(srv);
@@ -50,6 +71,7 @@ void aes67_rtsp_srv_init(struct aes67_rtsp_srv * srv, bool http_enabled, void *
 
     srv->listen_sockfd = -1;
     srv->client_sockfd = -1;
+    srv->blocking = true;
 }
 
 void aes67_rtsp_srv_deinit(struct aes67_rtsp_srv * srv)
@@ -59,7 +81,7 @@ void aes67_rtsp_srv_deinit(struct aes67_rtsp_srv * srv)
     aes67_rtsp_srv_stop(srv);
 
     while(srv->first_res){
-        aes67_rtsp_srv_sdp_remove(srv, srv->first_res);
+        aes67_rtsp_srv_sdp_remove(srv, srv->first_res->sdpref);
     }
 
     srv->state = aes67_rtsp_srv_state_init;
@@ -108,7 +130,7 @@ int aes67_rtsp_srv_start(struct aes67_rtsp_srv * srv, const enum aes67_net_ipver
     }
 
 
-    if (sock_nonblock(srv->listen_sockfd)){
+    if (sock_set_blocking(srv->listen_sockfd, srv->blocking)){
         fprintf(stderr, "Couldn't change non-/blocking\n");
         return EXIT_FAILURE;
     }
@@ -123,16 +145,31 @@ void aes67_rtsp_srv_stop(struct aes67_rtsp_srv * srv)
     assert(srv);
 
     if (srv->client_sockfd != -1){
+        sock_set_blocking(srv->client_sockfd, true);
         close(srv->client_sockfd);
         srv->client_sockfd = -1;
     }
 
     if (srv->listen_sockfd != -1){
+        sock_set_blocking(srv->listen_sockfd, true);
         close(srv->listen_sockfd);
         srv->listen_sockfd = -1;
     }
 }
 
+
+void aes67_rtsp_srv_blocking(struct aes67_rtsp_srv * srv, bool blocking)
+{
+    assert(srv);
+
+    if (srv->listen_sockfd != -1){
+        sock_set_blocking(srv->listen_sockfd, blocking);
+    }
+    if (srv->client_sockfd != -1){
+        sock_set_blocking(srv->client_sockfd, blocking);
+    }
+}
+
 void aes67_rtsp_srv_process(struct aes67_rtsp_srv * srv)
 {
     assert(srv);
@@ -142,8 +179,9 @@ void aes67_rtsp_srv_process(struct aes67_rtsp_srv * srv)
     }
     if (srv->state == aes67_rtsp_srv_state_listening) {
 
+        socklen_t socklen;
         if ((srv->client_sockfd = accept(srv->listen_sockfd, (struct sockaddr *) &srv->client_sockfd,
-                                         sizeof(srv->client_sockfd))) != -1) {
+                                         &socklen)) != -1) {
 
             srv->state = aes67_rtsp_srv_state_receiving;
             srv->req.proto = aes67_rtsp_srv_proto_undefined;
@@ -153,13 +191,24 @@ void aes67_rtsp_srv_process(struct aes67_rtsp_srv * srv)
             srv->req.CR = 0;
             srv->res.status_code = 0;
 
+            sock_set_blocking(srv->client_sockfd, srv->blocking);
+
             u8_t ipstr[AES67_NET_ADDR_STR_MAX];
-            u8_t iplen = aes67_net_ip2str(ipstr, aes67_net_ipver_4, srv->client_addr.sin_addr.s_addr, ntohs(srv->client_addr.sin_port));
+            u8_t iplen = aes67_net_ip2str(ipstr, aes67_net_ipver_4, (u8_t*)&srv->client_addr.sin_addr.s_addr, ntohs(srv->client_addr.sin_port));
             ipstr[iplen] = '\0';
 
             fprintf(stderr, "RTSP SRV connection from %s\n", ipstr);
         }
+        return;
     }
+
+    //sanity check
+    if (srv->client_sockfd == -1){
+        srv->state = aes67_rtsp_srv_state_listening;
+        return;
+    }
+
+
     if (srv->state == aes67_rtsp_srv_state_receiving){
 
         ssize_t r; // read result
@@ -200,7 +249,7 @@ void aes67_rtsp_srv_process(struct aes67_rtsp_srv * srv)
                             CR = srv->req.CR = 1;
                         }
 
-                        u8_t * s = srv->req.data_len - CR - sizeof("HTTP/1.0");
+                        u8_t * s = &srv->req.data[srv->req.data_len - CR - sizeof("HTTP/1.0")];
 
                         if (s[0] == 'H' &&
                             s[1] == 'T' &&
@@ -237,12 +286,13 @@ void aes67_rtsp_srv_process(struct aes67_rtsp_srv * srv)
                             return;
                         }
 
+                        // without proper validation
                         srv->req.version.major = s[5] - '0';
                         srv->req.version.minor = s[7] - '0';
 
                         s = srv->req.data;
 
-                        if (srv->req.proto = aes67_rtsp_srv_proto_rtsp &&
+                        if (srv->req.proto == aes67_rtsp_srv_proto_rtsp &&
                             s[0] == 'D' &&
                             s[1] == 'E' &&
                             s[2] == 'S' &&
@@ -253,6 +303,7 @@ void aes67_rtsp_srv_process(struct aes67_rtsp_srv * srv)
                             s[7] == 'E'
                                 ) {
                             srv->req.method = aes67_rtsp_srv_method_describe;
+                            srv->req.uri = &s[9];
                         }
                         else if (s[0] == 'O' && // supported by both rtsp and http
                                  s[1] == 'P' &&
@@ -263,30 +314,34 @@ void aes67_rtsp_srv_process(struct aes67_rtsp_srv * srv)
                                  s[6] == 'S'
                                 ) {
                             srv->req.method = aes67_rtsp_srv_method_options;
+                            srv->req.uri = &s[8];
                         }
-                        else if (srv->req.proto = aes67_rtsp_srv_proto_http &&
+                        else if (srv->req.proto == aes67_rtsp_srv_proto_http &&
                                  s[0] == 'G' &&
                                  s[1] == 'E' &&
                                  s[2] == 'T'
                                 ) {
                             srv->req.method = aes67_rtsp_srv_method_get;
+                            srv->req.uri = &s[4];
                         }
-                        else if (srv->req.proto = aes67_rtsp_srv_proto_http &&
+                        else if (srv->req.proto == aes67_rtsp_srv_proto_http &&
                                  s[0] == 'P' &&
                                  s[1] == 'O' &&
                                  s[2] == 'S' &&
                                  s[3] == 'T'
                                 ) {
                             srv->req.method = aes67_rtsp_srv_method_post;
+                            srv->req.uri = &s[5];
                         }
-                        else if (srv->req.proto = aes67_rtsp_srv_proto_http &&
+                        else if (srv->req.proto == aes67_rtsp_srv_proto_http &&
                                  s[0] == 'P' &&
                                  s[1] == 'U' &&
                                  s[2] == 'T'
                                 ) {
                             srv->req.method = aes67_rtsp_srv_method_put;
+                            srv->req.uri = &s[4];
                         }
-                        else if (srv->req.proto = aes67_rtsp_srv_proto_http &&
+                        else if (srv->req.proto == aes67_rtsp_srv_proto_http &&
                                  s[0] == 'D' &&
                                  s[1] == 'E' &&
                                  s[2] == 'L' &&
@@ -295,6 +350,7 @@ void aes67_rtsp_srv_process(struct aes67_rtsp_srv * srv)
                                  s[5] == 'E'
                                 ) {
                             srv->req.method = aes67_rtsp_srv_method_delete;
+                            srv->req.uri = &s[7];
                         }
                         else {
                             // method not supported/recognized, terminate without response
@@ -304,6 +360,41 @@ void aes67_rtsp_srv_process(struct aes67_rtsp_srv * srv)
                             return;
                         }
 
+                        // "RTSP/1.0" - "METHOD .."
+                        srv->req.urilen = &srv->req.data[srv->req.data_len - CR - sizeof("HTTP/1.0")] - srv->req.uri;
+
+                        printf("uri[%d] = %s", srv->req.urilen, srv->req.uri);
+                        // if  rtsp, discard scheme and host
+                        if (srv->req.proto == aes67_rtsp_srv_proto_rtsp){
+
+                            // basic validation
+                            if (srv->req.uri[0] != 'r' ||
+                                srv->req.uri[1] != 't' ||
+                                srv->req.uri[2] != 's' ||
+                                srv->req.uri[3] != 'p' ||
+                                srv->req.uri[4] != ':' ||
+                                srv->req.uri[5] != '/' ||
+                                srv->req.uri[6] != '/'
+                                    ){
+                                close(srv->client_sockfd);
+                                srv->client_sockfd = -1;
+                                srv->state = aes67_rtsp_srv_state_listening;
+                                return;
+                            }
+                            srv->req.uri += 7;
+                            srv->req.urilen -= 7;
+
+                            u8_t * delim = aes67_memchr(srv->req.uri, '/', srv->req.urilen);
+                            if (delim == NULL){
+                                close(srv->client_sockfd);
+                                srv->client_sockfd = -1;
+                                srv->state = aes67_rtsp_srv_state_listening;
+                                return;
+                            }
+
+                            srv->req.urilen -= delim - srv->req.uri;
+                            srv->req.uri = delim;
+                        }
 
                         // set line start
                         srv->req.line = &srv->req.data[srv->req.data_len];
@@ -406,14 +497,58 @@ void aes67_rtsp_srv_process(struct aes67_rtsp_srv * srv)
                     close(srv->client_sockfd);
                     srv->client_sockfd = -1;
                     srv->state = aes67_rtsp_srv_state_listening;
-                    printf("overflow\n");
+                    fprintf(stderr, "overflow\n");
                     return;
                 }
             }
         } // header
 
-        // read body
-    }
+        // read body (if total data is less than header and expected content length..)
+        u16_t missing = srv->req.content_length - (srv->req.data_len - srv->req.content_length);
+        if (missing > 0) {
+
+            // boundary check
+            if (srv->req.data_len + missing >= AES67_RTSP_SRV_RXBUFSIZE){
+                close(srv->client_sockfd);
+                srv->client_sockfd = -1;
+                srv->state = aes67_rtsp_srv_state_listening;
+                fprintf(stderr, "would overflow\n");
+                return;
+            }
+
+            r = read(srv->client_sockfd, &srv->req.data[srv->req.data_len], missing);
+
+            if (r == -1){ // timeout
+                return;
+            } else if (r == 0) { // closed prematurely
+                close(srv->client_sockfd);
+                srv->client_sockfd = -1;
+                srv->state = aes67_rtsp_srv_state_listening;
+                return;
+            } else if (r > 0) {
+                srv->req.data_len += r;
+                missing -= r;
+            }
+        }
+
+        if (missing == 0){
+            srv->state = aes67_rtsp_srv_state_processing;
+        }
+    } // state == aes67_rtsp_srv_state_receiving
+
+
+    if (srv->state == aes67_rtsp_srv_state_processing){
+        if (srv->req.proto == aes67_rtsp_srv_proto_rtsp){
+//            struct aes67_rtsp_srv_resource * res = rtsp_resource_by_uri(srv, )
+        } // proto == aes67_rtsp_srv_proto_rtsp
+        else if (srv->req.proto == aes67_rtsp_srv_proto_http){
+
+        } // proto == aes67_rtsp_srv_proto_http
+    } // state == aes67_rtsp_srv_state_processing
+
+    if (srv->state == aes67_rtsp_srv_state_sending){
+
+    } //state == aes67_rtsp_srv_state_sending
 }
 
 WEAK_FUN void aes67_rtsp_srv_sdp_getter(struct aes67_rtsp_srv * srv, void * sdpref, u8_t * buf, u16_t * len, u16_t maxlen)
@@ -427,7 +562,7 @@ WEAK_FUN void aes67_rtsp_srv_http_handler(struct aes67_rtsp_srv * srv, const enu
 }
 
 
-struct aes67_rtsp_srv_resource * aes67_rtsp_srv_sdp_add(struct aes67_rtsp_srv * srv, const char * uri, const u8_t urilen, const void * sdpref)
+struct aes67_rtsp_srv_resource * aes67_rtsp_srv_sdp_add(struct aes67_rtsp_srv * srv, const char * uri, const u8_t urilen, void * sdpref)
 {
     assert(srv);
     assert(uri);
-- 
GitLab