Send delayed ACKs after 200ms instead of 2500ms
[reactos.git] / reactos / drivers / lib / oskittcp / oskittcp / interface.c
index b525621..5da5c22 100644 (file)
@@ -1,5 +1,7 @@
 #include <oskittcp.h>
 #include <oskitdebug.h>
+#include <net/raw_cb.h>
+
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 #include <sys/uio.h>
 
-#ifdef WIN32
-#define snprintf _snprintf
-#endif//WIN32
-
 struct linker_set domain_set;
 
 OSKITTCP_EVENT_HANDLERS OtcpEvent = { 0 };
 
-OSK_UINT OskitDebugTraceLevel = OSK_DEBUG_ULTRA;
+//OSK_UINT OskitDebugTraceLevel = OSK_DEBUG_ULTRA;
+OSK_UINT OskitDebugTraceLevel = 0;
 
 /* SPL */
 unsigned cpl;
@@ -30,6 +29,10 @@ unsigned net_imask;
 unsigned volatile ipending;
 struct timeval boottime;
 
+void clock_init();
+int isprint(int c);
+int _snprintf(char * buf, size_t cnt, const char *fmt, ...);
+
 void *fbsd_malloc( unsigned int bytes, ... ) {
     if( !OtcpEvent.TCPMalloc ) panic("no malloc");
     return OtcpEvent.TCPMalloc
@@ -50,8 +53,6 @@ void InitOskitTCP() {
     raw_init();
     OS_DbgPrint(OSK_MID_TRACE,("Route Init\n"));
     route_init();
-    OS_DbgPrint(OSK_MID_TRACE,("Init fake freebsd scheduling\n"));
-    init_freebsd_sched();
     OS_DbgPrint(OSK_MID_TRACE,("Init clock\n"));
     clock_init();
     OS_DbgPrint(OSK_MID_TRACE,("Init TCP\n"));
@@ -65,14 +66,18 @@ void InitOskitTCP() {
 void DeinitOskitTCP() {
 }
 
-void TimerOskitTCP() {
-    tcp_slowtimo();
-    tcp_fasttimo();
+void TimerOskitTCP( int FastTimer, int SlowTimer ) {
+    if ( SlowTimer ) {
+        tcp_slowtimo();
+    }
+    if ( FastTimer ) {
+        tcp_fasttimo();
+    }
 }
 
 void RegisterOskitTCPEventHandlers( POSKITTCP_EVENT_HANDLERS EventHandlers ) {
     memcpy( &OtcpEvent, EventHandlers, sizeof(OtcpEvent) );
-    if( OtcpEvent.PacketSend ) 
+    if( OtcpEvent.PacketSend )
        OS_DbgPrint(OSK_MID_TRACE,("SendPacket handler registered: %x\n",
                                   OtcpEvent.PacketSend));
 }
@@ -91,7 +96,7 @@ void OskitDumpBuffer( OSK_PCHAR Data, OSK_UINT Len )
                if ( !align )
                {
                        if ( i ) DbgPrint( line );
-                       snprintf ( line, sizeof(line)-1, "%08x:                                                                  \n", &Data[i] );
+                       _snprintf ( line, sizeof(line)-1, "%08x:                                                                  \n", &Data[i] );
                        line[sizeof(line)-1] = '\0';
                }
 
@@ -108,16 +113,20 @@ void OskitDumpBuffer( OSK_PCHAR Data, OSK_UINT Len )
 /* From uipc_syscalls.c */
 
 int OskitTCPSocket( void *context,
-                   void **aso, 
-                   int domain, 
-                   int type, 
-                   int proto ) 
+                   void **aso,
+                   int domain,
+                   int type,
+                   int proto )
 {
     struct socket *so;
     int error = socreate(domain, &so, type, proto);
     if( !error ) {
        so->so_connection = context;
        so->so_state = SS_NBIO;
+       so->so_error = 0;
+        so->so_q = so->so_q0 = NULL;
+        so->so_qlen = 0;
+        so->so_head = NULL;
        *aso = so;
     }
     return error;
@@ -128,15 +137,16 @@ int OskitTCPRecv( void *connection,
                  OSK_UINT Len,
                  OSK_UINT *OutLen,
                  OSK_UINT Flags ) {
-    char *output_ptr = Data;
     struct uio uio = { 0 };
     struct iovec iov = { 0 };
     int error = 0;
     int tcp_flags = 0;
-    int tocopy = 0;
 
     *OutLen = 0;
 
+    OS_DbgPrint(OSK_MID_TRACE,
+                ("so->so_state %x\n", ((struct socket *)connection)->so_state));
+
     if( Flags & OSK_MSG_OOB )      tcp_flags |= MSG_OOB;
     if( Flags & OSK_MSG_DONTWAIT ) tcp_flags |= MSG_DONTWAIT;
     if( Flags & OSK_MSG_PEEK )     tcp_flags |= MSG_PEEK;
@@ -149,8 +159,8 @@ int OskitTCPRecv( void *connection,
     iov.iov_base = Data;
 
     OS_DbgPrint(OSK_MID_TRACE,("Reading %d bytes from TCP:\n", Len));
-       
-    error = soreceive( connection, NULL, &uio, NULL, NULL /* SCM_RIGHTS */, 
+
+    error = soreceive( connection, NULL, &uio, NULL, NULL /* SCM_RIGHTS */,
                       &tcp_flags );
 
     if( error == 0 ) {
@@ -159,34 +169,12 @@ int OskitTCPRecv( void *connection,
 
     return error;
 }
-                 
-static int
-getsockaddr(namp, uaddr, len)
-/* [<][>][^][v][top][bottom][index][help] */
-    struct sockaddr **namp;
-caddr_t uaddr;
-size_t len;
-{
-    struct sockaddr *sa;
-    int error;
-
-    if (len > SOCK_MAXADDRLEN)
-       return ENAMETOOLONG;
-    MALLOC(sa, struct sockaddr *, len, M_SONAME, M_WAITOK);
-    error = copyin(uaddr, sa, len);
-    if (error) {
-       FREE(sa, M_SONAME);
-    } else {
-       *namp = sa;
-    }
-    return error;
-}
 
 int OskitTCPBind( void *socket, void *connection,
                  void *nam, OSK_UINT namelen ) {
     int error = EFAULT;
     struct socket *so = socket;
-    struct mbuf sabuf = { 0 };
+    struct mbuf sabuf;
     struct sockaddr addr;
 
     OS_DbgPrint(OSK_MID_TRACE,("Called, socket = %08x\n", socket));
@@ -194,26 +182,24 @@ int OskitTCPBind( void *socket, void *connection,
     if( nam )
        addr = *((struct sockaddr *)nam);
 
+    RtlZeroMemory(&sabuf, sizeof(sabuf));
     sabuf.m_data = (void *)&addr;
     sabuf.m_len = sizeof(addr);
-    
+
     addr.sa_family = addr.sa_len;
     addr.sa_len = sizeof(struct sockaddr);
 
     error = sobind(so, &sabuf);
 
     OS_DbgPrint(OSK_MID_TRACE,("Ending: %08x\n", error));
-    return (error);    
+    return (error);
 }
 
-int OskitTCPConnect( void *socket, void *connection, 
+int OskitTCPConnect( void *socket, void *connection,
                     void *nam, OSK_UINT namelen ) {
     struct socket *so = socket;
-    struct connect_args _uap = {
-       0, nam, namelen
-    }, *uap = &_uap;
-    int error = EFAULT, s;
-    struct mbuf sabuf = { 0 };
+    int error = EFAULT;
+    struct mbuf sabuf;
     struct sockaddr addr;
 
     OS_DbgPrint(OSK_MID_TRACE,("Called, socket = %08x\n", socket));
@@ -229,9 +215,10 @@ int OskitTCPConnect( void *socket, void *connection,
     if( nam )
        addr = *((struct sockaddr *)nam);
 
+    RtlZeroMemory(&sabuf, sizeof(sabuf));
     sabuf.m_data = (void *)&addr;
     sabuf.m_len = sizeof(addr);
-    
+
     addr.sa_family = addr.sa_len;
     addr.sa_len = sizeof(struct sockaddr);
 
@@ -253,7 +240,11 @@ bad:
 
 done:
     OS_DbgPrint(OSK_MID_TRACE,("Ending: %08x\n", error));
-    return (error);    
+    return (error);
+}
+
+int OskitTCPShutdown( void *socket, int disconn_type ) {
+    return soshutdown( socket, disconn_type );
 }
 
 int OskitTCPClose( void *socket ) {
@@ -263,7 +254,7 @@ int OskitTCPClose( void *socket ) {
     return 0;
 }
 
-int OskitTCPSend( void *socket, OSK_PCHAR Data, OSK_UINT Len, 
+int OskitTCPSend( void *socket, OSK_PCHAR Data, OSK_UINT Len,
                  OSK_UINT *OutLen, OSK_UINT flags ) {
     struct mbuf* m = m_devget( Data, Len, 0, NULL, NULL );
     int error = 0;
@@ -274,30 +265,137 @@ int OskitTCPSend( void *socket, OSK_PCHAR Data, OSK_UINT Len,
     return error;
 }
 
-int OskitTCPAccept( void *socket, 
-                   void *AddrOut, 
+int OskitTCPAccept( void *socket,
+                   void **new_socket,
+                   void *AddrOut,
                    OSK_UINT AddrLen,
-                   OSK_UINT *OutAddrLen ) {
-    struct mbuf nam;
-    int error;
+                   OSK_UINT *OutAddrLen,
+                   OSK_UINT FinishAccepting ) {
+    struct socket *head = (void *)socket;
+    struct sockaddr *name = (struct sockaddr *)AddrOut;
+    struct socket **newso = (struct socket **)new_socket;
+    struct socket *so = socket;
+    struct sockaddr_in sa;
+    struct mbuf mnam;
+    struct inpcb *inp;
+    int namelen = 0, error = 0, s;
+
+    OS_DbgPrint(OSK_MID_TRACE,("OSKITTCP: Doing accept (Finish %d)\n",
+                              FinishAccepting));
+
+    *OutAddrLen = AddrLen;
+
+    if (name)
+       /* that's a copyin actually */
+       namelen = *OutAddrLen;
+
+    s = splnet();
+
+#if 0
+    if ((head->so_options & SO_ACCEPTCONN) == 0) {
+       splx(s);
+       OS_DbgPrint(OSK_MID_TRACE,("OSKITTCP: head->so_options = %x, wanted bit %x\n",
+                                  head->so_options, SO_ACCEPTCONN));
+       error = EINVAL;
+       goto out;
+    }
+#endif
+
+    OS_DbgPrint(OSK_MID_TRACE,("head->so_q = %x, head->so_state = %x\n",
+                              head->so_q, head->so_state));
 
-    nam.m_data = AddrOut;
-    nam.m_len  = AddrLen;
+    if ((head->so_state & SS_NBIO) && head->so_q == NULL) {
+       splx(s);
+       error = EWOULDBLOCK;
+       goto out;
+    }
+
+    OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
+    while (head->so_q == NULL && head->so_error == 0) {
+       if (head->so_state & SS_CANTRCVMORE) {
+           head->so_error = ECONNABORTED;
+           break;
+       }
+       OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
+       error = tsleep((caddr_t)&head->so_timeo, PSOCK | PCATCH,
+                      "accept", 0);
+       if (error) {
+           splx(s);
+           goto out;
+       }
+       OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
+    }
+    OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
+
+#if 0
+    if (head->so_error) {
+       OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
+       error = head->so_error;
+       head->so_error = 0;
+       splx(s);
+       goto out;
+    }
+    OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
+#endif
+
+    /*
+     * At this point we know that there is at least one connection
+     * ready to be accepted. Remove it from the queue.
+     */
+    so = head->so_q;
+
+    inp = so ? (struct inpcb *)so->so_pcb : NULL;
+    if( inp ) {
+        ((struct sockaddr_in *)AddrOut)->sin_addr.s_addr =
+            inp->inp_faddr.s_addr;
+        ((struct sockaddr_in *)AddrOut)->sin_port = inp->inp_fport;
+    }
+
+    OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
+    if( FinishAccepting ) {
+       head->so_q = so->so_q;
+       head->so_qlen--;
 
-    return soaccept( socket, &nam );
+       *newso = so;
+
+       /*so->so_state &= ~SS_COMP;*/
+
+       mnam.m_data = (char *)&sa;
+       mnam.m_len = sizeof(sa);
+
+       (void) soaccept(so, &mnam);
+
+       so->so_state = SS_NBIO | SS_ISCONNECTED;
+        so->so_q = so->so_q0 = NULL;
+        so->so_qlen = 0;
+        so->so_head = 0;
+
+       OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
+       if (name) {
+           /* check sa_len before it is destroyed */
+           memcpy( AddrOut, &sa, AddrLen < sizeof(sa) ? AddrLen : sizeof(sa) );
+           OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
+           *OutAddrLen = namelen;      /* copyout actually */
+       }
+       OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
+       splx(s);
+    }
+out:
+    OS_DbgPrint(OSK_MID_TRACE,("OSKITTCP: Returning %d\n", error));
+    return (error);
 }
 
 /* The story so far
- * 
+ *
  * We have a packet.  While we store the fields we want in host byte order
  * outside the original packet, the bsd stack modifies them in place.
  */
 
-void OskitTCPReceiveDatagram( OSK_PCHAR Data, OSK_UINT Len, 
+void OskitTCPReceiveDatagram( OSK_PCHAR Data, OSK_UINT Len,
                              OSK_UINT IpHeaderLen ) {
     struct mbuf *Ip = m_devget( Data, Len, 0, NULL, NULL );
     struct ip *iph;
-    
+
     if( !Ip ) return; /* drop the segment */
 
     //memcpy( Ip->m_data, Data, Len );
@@ -308,7 +406,7 @@ void OskitTCPReceiveDatagram( OSK_PCHAR Data, OSK_UINT Len,
     NTOHS(iph->ip_len);
     iph->ip_len -= sizeof(struct ip);
 
-    OS_DbgPrint(OSK_MAX_TRACE, 
+    OS_DbgPrint(OSK_MAX_TRACE,
                ("OskitTCPReceiveDatagram: %d (%d header) Bytes\n", Len,
                 IpHeaderLen));
 
@@ -318,46 +416,46 @@ void OskitTCPReceiveDatagram( OSK_PCHAR Data, OSK_UINT Len,
 }
 
 int OskitTCPListen( void *socket, int backlog ) {
-    return solisten( socket, backlog );
+    int error;
+
+    OS_DbgPrint(OSK_MID_TRACE,("Called, socket = %08x\n", socket));
+    error = solisten( socket, backlog );
+    OS_DbgPrint(OSK_MID_TRACE,("Ending: %08x\n", error));
+
+    return error;
 }
 
-void OskitTCPSetAddress( void *socket, 
+void OskitTCPSetAddress( void *socket,
                         OSK_UINT LocalAddress,
                         OSK_UI16 LocalPort,
                         OSK_UINT RemoteAddress,
                         OSK_UI16 RemotePort ) {
     struct socket *so = socket;
-    struct inpcb *inp = so->so_pcb;
+    struct inpcb *inp = (struct inpcb *)so->so_pcb;
     inp->inp_laddr.s_addr = LocalAddress;
     inp->inp_lport = LocalPort;
     inp->inp_faddr.s_addr = RemoteAddress;
     inp->inp_fport = RemotePort;
-    DbgPrint("OSKIT: SET ADDR %x:%x -> %x:%x\n", 
-            LocalAddress, LocalPort,
-            RemoteAddress, RemotePort);
 }
 
-void OskitTCPGetAddress( void *socket, 
+void OskitTCPGetAddress( void *socket,
                         OSK_UINT *LocalAddress,
                         OSK_UI16 *LocalPort,
                         OSK_UINT *RemoteAddress,
                         OSK_UI16 *RemotePort ) {
     struct socket *so = socket;
-    struct inpcb *inp = so ? so->so_pcb : 0;
+    struct inpcb *inp = so ? (struct inpcb *)so->so_pcb : NULL;
     if( inp ) {
        *LocalAddress = inp->inp_laddr.s_addr;
        *LocalPort = inp->inp_lport;
        *RemoteAddress = inp->inp_faddr.s_addr;
        *RemotePort = inp->inp_fport;
-       DbgPrint("OSKIT: GET ADDR %x:%x -> %x:%x\n", 
-                *LocalAddress, *LocalPort,
-                *RemoteAddress, *RemotePort);
     }
 }
 
 struct ifaddr *ifa_iffind(struct sockaddr *addr, int type)
 {
-    if( OtcpEvent.FindInterface ) 
+    if( OtcpEvent.FindInterface )
        return OtcpEvent.FindInterface( OtcpEvent.ClientData,
                                        PF_INET,
                                        type,
@@ -470,9 +568,9 @@ struct ifaddr *ifa_ifwithnet(addr)
 
     if( ifaddr )
     {
-       sin = (struct sockaddr *)&ifaddr->ifa_addr;
+       sin = (struct sockaddr_in *)&ifaddr->ifa_addr;
 
-       OS_DbgPrint(OSK_MID_TRACE,("ifaddr->addr = %x\n", 
+       OS_DbgPrint(OSK_MID_TRACE,("ifaddr->addr = %x\n",
                                   sin->sin_addr.s_addr));
     }