/*
    NetUDPModuleUp.c, Copyright  (c) by Boris Lutz,
    Swiss Federal Institute of Technology,
    Computer Engineering and Networks Laboratory.
 
    TOPSY -- A Teachable Operating System.
             Implementation of a tiny and simple
             micro kernel for teaching purposes.
 
    For further information, please visit http://www.tik.ee.ethz.ch/~topsy
 
    This software is provided under the terms of the GNU General Public
    Licence. A full copy of the GNU GPL is provided in the file COPYING
    found in the development root of Topsy.
*/
/*
 
    File:                  $Source: /home/ruf/cvs_Topsy/cvs/Topsy/Net/Modules/UDP/NetUDPModuleUp.c,v $
    Author(s):
    Affiliation:           ETH Zuerich, TIK
    Version:               $Revision: 2922 $
    Creation Date:
    Last Date of Change:   $Date: 2007-03-19 17:48:52 +0100 (Mon, 19 Mär 2007) $  by: $Author: baderma $
 
*/
#include "NetModulesNew.h"
#include "NetAttr.h"
#include "LWThreads.h"
#include "NetBitFields.h"
#include "NetByteorder.h"
#include "NetDebug.h"
#include "NetIPChecksum.h"
#include "NetUDPChecksum.h"
#include "NetUDPModule.h"


void netUDPModuleUpInit (NetModule this)
{
  // XXX what should I do?
  return;
}


int netUDPModuleUpConfig (NetModule this, Message *msg)
{
  return 0;
}


void netUDPModuleUpMain (LWPool lw, ThreadArg arg)
{
  NetModule		modDesc = (NetModule) arg;
  NetUDPHdr		*hdr;
  unsigned short	tLen,
  hLen,
  sPort,
  dPort;
  int				cSum;
  NetBuf			data;
  NetAttrs		meta;


  while (1)
  {
    netmodRecv (lw, &data, &meta);
    PACKSTART(modDesc);

    netdbgPrintf( NETDEBUG_UDP, "netUDPModuleUp: received UDP up\n");



    hdr = (NetUDPHdr*) NETBUF_DATA(data);

    /* Verify minimal length */
    tLen = netbufLen(data);
    if (tLen < sizeof(NetUDPHdr) )
    {
      PACKERROR(modDesc);
      netmodRIP (lw, data, meta,
                 "netudp: Packet size smaller than minimal length!");
      continue;
    }
    /* Verify and set attributes stated length (in header) */
    hLen = ntohs(hdr->len);
    if (tLen != hLen )
    {
      PACKERROR(modDesc);
      netmodRIP (lw, data, meta, "netudp: bad packet size\n");
      continue;
    }
    netattrSet(meta, NETATTR_UDP_LENGTH, hLen);

    /* Verify and setattr checksum (facultative) */
    cSum = ntohs(hdr->checksum);
    if(cSum)
    {
      if(netudpChecksum(data, meta, tLen))
      {
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "netudp: Checksum failed!");
        continue;
      }
    }
    netattrSet(meta, NETATTR_UDP_CHECKSUM, cSum);

    /* Set source and destination port */
    sPort = ntohs(hdr->sport);
    netattrSet(meta, NETATTR_UDP_LOCAL, sPort);
    dPort = ntohs(hdr->dport);
    netattrSet(meta, NETATTR_UDP_REMOTE, dPort);

    /* Strip  header */
    data->start += sizeof(NetUDPHdr);
    netdbgPrintf( NETDEBUG_UDP, "netUDPModuleUp: finished UDP up\n");
    PACKDONE(modDesc);
    netmodSend (lw, CHAINNEXT(modDesc), data, meta);
  }
}

