/*
    Copyright 2000 (c) by Authors,
    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/Topsy/Socket.c,v $
    Affiliation:           ETH Zuerich, TIK
    Version:               $Revision: 2922 $
    Last Date of Change:   $Date: 2007-03-19 17:48:52 +0100 (Mon, 19 Mär 2007) $  by: $Author: baderma $
 
*/

#include "Topsy.h"
#include "Syscall.h"
#include "Support.h"
#include "NetConfigMngr.h"
#include "NetDebug.h"
#include "NetError.h"
#include "NetAttr.h"
#include "NetSocket.h"
#include "NetProtocols.h"
#include "NetMemoryManager.h"
#include "Socket.h"


extern ThreadId		netConfigThread;
extern IODeviceDesc	socketDesc;



ThreadId socketXXX (unsigned short  domain, unsigned short type, unsigned short proto)
{
  ThreadId		t;
  unsigned short	minor;


  // this stuff is done locally not by the ConfigMngr since
  // it is busy getting the PCB when I do a ioLoad... XXX
  hmAlloc ( &(socketDesc.extension), sizeof(SocketDesc));
  ((SocketDesc*) socketDesc.extension)->so_domain = domain;
  ((SocketDesc*) socketDesc.extension)->so_type = type;
  /* XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
     XXX THIS IS A BRUTE HACK TO GET THE STUFF WORKING, DON'T EVEN
     XXX TRY TO USE THIS IN A LATER RELEASE. INSTEAD THE SOCKET DEVICE
     XXX SHOULD BE MODIFIED TO SUPPORT PROTOCOLS IN A DYNAMICAL WAY
     XXX LIKE THE BSD SOCKET 2001026 CJ XXX
     XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX */
  switch ( proto )
  {
  case PROTO_TCP:
  case PROTO_UDP:
    ((SocketDesc*) socketDesc.extension)->so_protocol = proto;
    break;
  case 0:
    if ( type == SOCK_STREAM )
      ((SocketDesc*) socketDesc.extension)->so_protocol = PROTO_TCP;
    else if ( type == SOCK_DGRAM )
      ((SocketDesc*) socketDesc.extension)->so_protocol = PROTO_UDP;
    else
      return 0;
    break;
  }

  if (ioLoad (SOCKET, &socketDesc, &minor) == IO_LOADFAILED)
  {
    netdbgPrintf(NETDEBUG_SOCKET, "socket: ioLoad failed!\n");
    return 0;
  }
  else
  {
    if (ioOpen(SOCKET, minor, &t) == IO_OPENFAILED)
    {
      netdbgPrintf(NETDEBUG_SOCKET, "socket: ioOpen failed!\n");
      return 0;
    }
    else
    {
      //netdbgPrintf (NETDEBUG_SOCKET, "Socket: domain = %i  type = %i  minor = %i
      //		socket = %i\n", domain, type, minor, t);
      return t;
    }
  }
}


Error connectXXX (ThreadId mySock, NetAttr *attrVecAddr, unsigned long addrLen)
{
  Message		msg,
  reply;


  msg.id = CONNECT;
  msg.msg.netSockBindConnect.attrVec = attrVecAddr;
  msg.msg.netSockBindConnect.len = addrLen;
  reply.id = NET_SOCKET_CONNECTED;

  if ( genericSyscall(mySock, &msg, &reply) == TM_MSGSENDFAILED)
  {
    netdbgPrintf (NETDEBUG_SOCKET, "socket: failed to connect!\n");
    return SOCKET_FAILED;
  }
  return reply.msg.netConfReply.errno;
}


Error bindXXX (ThreadId mySock, NetAttr *attrVecAddr, unsigned long addrLen)
{
  Message		msg,
  reply;


  msg.id = BIND;
  msg.msg.netSockBindConnect.attrVec = attrVecAddr;
  msg.msg.netSockBindConnect.len = addrLen;
  reply.id = NET_SOCKET_CONNECTED;

  if ( genericSyscall(mySock, &msg, &reply) == TM_MSGSENDFAILED)
  {
    netdbgPrintf (NETDEBUG_SOCKET, "socket: failed to bind!\n");
    return SOCKET_FAILED;
  }
  return reply.msg.netConfReply.errno;
}
