/*
  udp.h contains a  minimum UNIX interface
  in order to use UDP protocol

  Miguel Masmano <mmasmano@disca.upv.es>

  Copyright (C) OCERA Consortium Sept. 2003
  Released under the terms of the GPL v2 license
*/

#ifndef _UDP_PROT_H_
#define _UDP_PROT_H_
#include <pthread.h>
#include "ip.h"

/***************************/
#define MAX_NUMBER_OF_SOCKETS 20 // MAX_NUMBER_OF_SOCKETS defines
                                 // the total number of sockets
                                 // which can be used at the 
                                 // same time
/***************************/

#ifndef INADDR_ANY
#define    INADDR_ANY              ((unsigned long int) 0x00000000)
#endif

// Not standard Flag which can be used with the recv and recvfrom
// function. 
#define S_ASYNC 0x8

#ifdef MARTE_STANDALONE
#define PF_INET 1 // IPv4
#define AF_INET 2 // IPv4

#define SOCK_STREAM 11 // TCP - not implemented
#define SOCK_DGRAM 12 // UDP

/* Some definitions taken from Linux include files */
typedef unsigned int size_t;
typedef unsigned short int sa_family_t;

struct sockaddr {
  sa_family_t     sa_family;      /* address family, AF_xxx       */
  char            sa_data[14];    /* 14 bytes of protocol address */
};

struct sockaddr_in {
  sa_family_t           sin_family;     /* Address family               */
  unsigned short int    sin_port;       /* Port number                  */
  struct in_addr        sin_addr;       /* Internet address             */

  /* Pad to size of `struct sockaddr'. */
  unsigned char         __pad[__SOCK_SIZE__ - sizeof(short int) -
                        sizeof(unsigned short int) - sizeof(struct in_addr)];
};

#else

#include <linux/slab.h>
#include <linux/in.h>

#endif

typedef unsigned int socklen_t;

enum socket_status {NOT_USED, EMPTY, FULL};

#ifdef MARTE_STANDALONE
typedef struct sockets_struct {
  struct sockaddr_in addr;
  struct sockaddr_in recv_addr;
  socklen_t addrlen;
  int sync_thread;
  pthread_mutex_t suspend_mutex;
  enum socket_status status;
  pthread_mutex_t suspend_mutex;
  char info_recv [1600];
} sockets_t;
#else
typedef struct sockets_struct {
  struct sockaddr_in addr;
  struct sockaddr_in recv_addr;
  socklen_t addrlen;
  int sync_thread;
  pthread_mutex_t suspend_mutex;
  enum socket_status status;
  char *info_recv;
  int size_info_recv;
} sockets_t;
#endif

extern sockets_t table_sockets [];

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

int bind (int sockfd, struct sockaddr *my_addr, socklen_t addrlen);

int close_socket_np (int sockfd);

int  connect (int sockfd,  const  struct sockaddr *serv_addr, socklen_t
	      addrlen);

// It is a TCP operation, it will always returns an error
int listen (int sockfd, int backlog);

/* By default this call is synchronous, but
 * using the S_ASYNC flag, it will be asynchronous */
int recv (int sockfd, void *buf, size_t len, int flags);

/* By default this call is synchronous, but
 * using the S_ASYNC flag, it will be asynchronous */
int recvfrom (int sockfd, void *buf, size_t len, int flags, struct sockaddr
	      *from, socklen_t *lenfrom);

/* flags is not used */
int send (int sockfd, const void *msg, size_t len, int flags);

/* flags is not used */
int sendto (int sockfd, const void *msg, size_t len, int flags, const struct
	    sockaddr *to, socklen_t tolen);

int shutdown (int sockfd, int how);

int socket (int domain, int type, int protocol);

// called by init_module in ip.c
int init_udp_prot (void);

// called by cleanup_module in ip.c
void uninit_udp_prot (void);

#endif
