Hi everybody...

        I was wondering what was the status of unreliable connections
on top of TinyTP (chapt 2.2.4 of the spec). Boy, you should never ask
those kind of questions when you have nothing to do in the evening...
        With the following patch, I'm able to send and receive data
unreliably over the Ir link. In fact, it's so unreliable that if you
don't pace your message the IrDA stack goes kaputt.

        To use this service, just replace SOCK_STREAM by
SOCK_SEQPACKET in your application. As opposed to UDP, this is a
connected service, so you are supposed to use connect/listen-accept
before sending data. And also, as mentionned above, now flow control.
        IAS doesn't allow to distinguish the two type of services, so
you don't know what the application on the other end will
support. I've added the feature that a SOCK_STREAM app can exchange
data with a SOCK_SEQPACKET application.
        I did my best to read the spec and try to be logical, but I
didn't have the chance to see what other implementations are doing on
the subject...

        Dag : could you please have a look at this patch ? Also, you
could add a feature to the example in irda-utils/irsockets to select
the type of service you want...

        Have fun...

        Jean

----------------------------------------
--- af_irda.old.c       Fri Dec  3 14:19:01 1999
+++ af_irda.c   Fri Dec  3 16:08:57 1999
@@ -1,7 +1,7 @@
 /*********************************************************************
  *                
  * Filename:      af_irda.c
- * Version:       0.7
+ * Version:       0.7.1
  * Description:   IrDA sockets implementation
  * Status:        Experimental.
  * Author:        Dag Brattli <[EMAIL PROTECTED]>
@@ -23,6 +23,13 @@
  *     
  ********************************************************************/
 
+/*
+ * 0.7 -> 0.7.1 - Jean Tourrilhes
+ *     o Make SOCK_SEQPACKET sockets send unreliable frames
+ *     o Allow to listen and accept in SOCK_SEQPACKET sockets
+ *     o Allow to receive unreliable frames
+ */
+
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
@@ -353,6 +360,7 @@ static int irda_open_tsap(struct irda_so
        notify.connect_indication    = irda_connect_indication;
        notify.disconnect_indication = irda_disconnect_indication;
        notify.data_indication       = irda_data_indication;
+       notify.udata_indication      = irda_data_indication;
        notify.flow_indication       = irda_flow_indication;
        notify.instance = self;
        strncpy(notify.name, name, NOTIFY_MAX_NAME);
@@ -448,7 +456,8 @@ static int irda_listen(struct socket *so
 
        IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
-       if (sk->type == SOCK_STREAM && sk->state != TCP_LISTEN) {
+       if (((sk->type == SOCK_STREAM) || (sk->type == SOCK_SEQPACKET))
+           && (sk->state != TCP_LISTEN)) {
                sk->max_ack_backlog = backlog;
                sk->state           = TCP_LISTEN;
 
@@ -530,7 +539,7 @@ static int irda_accept(struct socket *so
        if ((sk = sock->sk) == NULL)
                return -EINVAL;
 
-       if (sk->type != SOCK_STREAM)
+       if ((sk->type != SOCK_STREAM) && (sk->type != SOCK_SEQPACKET))
                return -EOPNOTSUPP;
 
        if (sk->state != TCP_LISTEN)
@@ -852,6 +861,12 @@ static int irda_sendmsg(struct socket *s
        }
 
        /* Check that we don't send out to big frames */
+       /* I'm not sure, but I believe that around here we should split
+        * big frames into smaller chunk and perform coalesce on smaller
+        * chunks to group them in bigger packets, as it is done
+        * in 'tcp_do_sendmsg'...
+        * As the service is reliable AND sequenced, the higher layer won't
+        * see the difference and the performance will be better... */
        if (len > self->max_data_size) {
                IRDA_DEBUG(0, __FUNCTION__ "(), Warning to much data! "
                      "Chopping frame from %d to %d bytes!\n", len, 
@@ -883,6 +898,71 @@ static int irda_sendmsg(struct socket *s
 }
 
 /*
+ * Function irda_sendmsg_dgram (sock, msg, len, scm)
+ *
+ *    Send message down to TinyTP for the unreliable sequenced
+ *    packet service...
+ *
+ */
+static int irda_sendmsg_dgram(struct socket *sock, struct msghdr *msg,
+                             int len, struct scm_cookie *scm)
+{
+       struct sock *sk = sock->sk;
+/*     struct sockaddr_irda *addr = (struct sockaddr_irda *) msg->msg_name; */
+       struct irda_sock *self;
+       struct sk_buff *skb;
+       unsigned char *asmptr;
+       int err;
+
+       IRDA_DEBUG(4, __FUNCTION__ "(), len=%d\n", len);
+
+       if (msg->msg_flags & ~MSG_DONTWAIT)
+               return -EINVAL;
+
+       if (sk->shutdown & SEND_SHUTDOWN) {
+               send_sig(SIGPIPE, current, 0);
+               return -EPIPE;
+       }
+
+       if (sk->state != TCP_ESTABLISHED)
+               return -ENOTCONN;
+
+       self = sk->protinfo.irda;
+       ASSERT(self != NULL, return -1;);
+
+       /* Check that we don't send out to big frames */
+       /* Unreliable service : no fragmentation, no coalescence */
+       if (len > self->max_data_size) {
+               IRDA_DEBUG(0, __FUNCTION__ "(), Warning to much data! "
+                     "Chopping frame from %d to %d bytes!\n", len, 
+                     self->max_data_size);
+               len = self->max_data_size;
+       }
+
+       skb = sock_alloc_send_skb(sk, len + self->max_header_size, 0, 
+                                 msg->msg_flags & MSG_DONTWAIT, &err);
+       if (!skb)
+               return -ENOBUFS;
+
+       skb_reserve(skb, self->max_header_size);
+       
+       IRDA_DEBUG(4, __FUNCTION__ "(), appending user data\n");
+       asmptr = skb->h.raw = skb_put(skb, len);
+       memcpy_fromiovec(asmptr, msg->msg_iov, len);
+
+       /* 
+        * Just send the message to TinyTP, and let it deal with possible 
+        * errors. No need to duplicate all that here
+        */
+       err = irttp_udata_request(self->tsap, skb);
+       if (err) {
+               IRDA_DEBUG(0, __FUNCTION__ "(), err=%d\n", err);
+               return err;
+       }
+       return len;
+}
+
+/*
  * Function irda_recvmsg (sock, msg, size, flags, scm)
  *
  *    Try to receive message and copy it to user
@@ -1386,7 +1466,7 @@ static struct proto_ops irda_dgram_ops =
        irda_setsockopt,
        irda_getsockopt,
        sock_no_fcntl,
-       irda_sendmsg,
+       irda_sendmsg_dgram,
        irda_recvmsg_dgram,
 };
 

_______________________________________________
Linux-IrDA mailing list  -  [EMAIL PROTECTED]
http://www4.pasta.cs.UiT.No/mailman/listinfo/linux-irda

Reply via email to