//
//               Copyright (C) 2005, BroadOn Communications Corp.
//
//  These coded instructions, statements, and computer programs contain
//  unpublished  proprietary information of BroadOn Communications Corp.,
//  and  are protected by Federal copyright law. They may not be disclosed
//  to  third  parties or copied or duplicated in any form, in whole or in
//  part, without the prior written consent of BroadOn Communications Corp.
//
//

// This is the public interface to the BroadOn online services for
// internet gaming, and includes the VNG and VN interfaces.
//
// The following conventions are used.
//   - Any const ptr is an input parameter,
//   - a non-const ptr to an incomplete type is an input/output parameter,
//   - any other non-const ptr is an output parameter.
//   - Where these rules do not apply, it is indicated in comments.
//
// This interface was defined for an ISO C99 compliant compiler and is
// intended for cross platform development.  However, some compilers
// used for cross platform are not ISO C99 compliant (including the
// latest version of MS Windows VC7).  Conditional compilation is
// necessary to suport compilation across the various compilers.
//


#ifndef __VNG_H__
#define __VNG_H__  1

#include <stddef.h>
#include <string.h>
#include "vng_types.h"

#ifdef __cplusplus
extern "C" {
#endif


#if defined (_WIN32) && defined(_SC_SDK)
    // The following ifdef block is the standard way of creating macrosg
    // which make exporting from a DLL simpler. All files within this DLLS
    // are compiled with the LIBVNG_EXPORT symbol defined on the command
    // line. this symbol should not be defined on any project that uses
    // this DLL. This way any other project whose source files include
    // this file see LIBVNG_API functions as being imported from a DLL,
    // whereas this DLL sees symbols defined with this macro as being
    // exported.
    #ifdef LIBVNG_EXPORTS
        #define LIBVNG_API __declspec(dllexport)
    #else
        #define LIBVNG_API __declspec(dllimport)
    #endif
#else
    #define LIBVNG_API
#endif

// The following is used to align structs and struct members
// on 32 bit boundaries,  This is needed to match GBA packing
// and by the implementation of internal VNG communication
// between VNG windows clients and the linux based VNG server.
//
// The previous pack value is restored at the end of this file.
//
// The version of the compiler used for GBA and NETC
// does not support this pragma.
//
#if !defined(_GBA) && !defined(_SC)
#pragma pack(push, 4)
#endif



//-----------------------------------------------------------
//---------------------- Error handling
//-----------------------------------------------------------

// Error handling:  We define a non-contiguous enumeration of error
// codes and the translation from an error code to a descriptive
// out-of-context (invariant) string.  Other than VNG_OK,
// the error codes define fatal or non-fatal errors.
//

typedef enum {
    VNG_OK      = 0,
    //
    // General error codes (1-15)
    //
    VNGERR_UNKNOWN = 1,
    VNGERR_NOWAIT = 2,         // Non-blocking call returns immediately
    VNGERR_TIMEOUT = 3,        // Timeout before service could complete
    VNGERR_NO_VN_SERVER = 4,   // API requires vn server connection
    VNGERR_NOT_LOGGED_IN = 5,  // Attempted action that requires login
    VNGERR_OVERFLOW = 6,       // Output value buffer overflow
    VNGERR_NOMEM = 7,          // out-of-memory
    VNGERR_FINI = 8,           // VNG session terminated or not initialized
    VNGERR_NOT_FOUND = 9,      // Info being retrieved was not found
    VNGERR_BUF_FULL = 10,      // Internal buffer was full
                               //   example: send failed becase buffer full
    VNGERR_NOT_SUPPORTED = 11, // Feature is not currently supported
    VNGERR_INFRA_NS = 12,      // VNG infrastructure server returned a
                               // non-specific error.
    VNGERR_GAME_SERVER = 13,   // online game server is down

    // Peer and server communication problems (16-31)
    //
    VNGERR_CONN_REFUSED = 16, // Connection refused
    VNGERR_UNREACHABLE = 17,  // Cannot connect


    // Login related problems (32-47)
    //
    VNGERR_INVALID_LOGIN = 32,  // The login name or passwd is not valid

    // Buddy list, black list, and matchmaking related problems (48-63)
    //
    VNGERR_NOT_INVITED = 48,    // Attempted reject/accept without invite
    VNGERR_UNKNOWN_NAME = 49,   // Unknown subscriber name
    VNGERR_INVALID_ACTION = 50, // buddy action not allowed

    // Game VN related problems in the range 64-79
    //
    VNGERR_VN_ENDED = 64,          // The game ended or was aborted
    VNGERR_VN_JOIN_DENIED = 65,    // Host/server denied a join request
    VNGERR_VN_MISSING_PROC = 66,   // Missing RPC procedure
    VNGERR_VN_MISSING_STATUS = 67, // Missing session status value
    VNGERR_VN_NOT_HOST = 68,       // API is only valid for the VN owner

    // API argument related errors in the range 90 to 99
    //
    VNGERR_INVALID_ARG  = 90, // An argument to the API is invalid
    VNGERR_INVALID_VNG  = 91, // VNG associated with an API is invalid
    VNGERR_INVALID_VN   = 92, // VN associated with an API is invalid
    VNGERR_INVALID_MEMB = 93, // VNMember associated with API is invalid
    VNGERR_INVALID_LEN  = 94, // Length argument to an API is invalid
                              // or null terminated string is too long

    // Stored Message specific errors
    //
    VNGERR_MAILBOX_FULL  = 110, // Recipient has max allowed stored messages
    VNGERR_OUTBOX_FULL   = 111, // Sender has sent max allowed stored messages
    VNGERR_STM_SEND      = 112, // Msg not stored because of send failure
    VNGERR_STM_DELETE    = 113, // Attempt to delete msg for which
                                // current login was not a recipient

    // Voice related errors
    //
    VNGERR_VOICE_IN_USE = 120,  // Voice is already in use by the user

    // Resource Manager errors
    //
    VNGERR_RM_API      = 130, // Error while attempting to access a VNG API
    VNGERR_ACCESS      = 131, // Calling thread does not have permission
    VNGERR_MAX_REACHED = 132, // A limited resource has reached its max


    // Insert error codes before this line and increment the MAX below
    //
    VNGERR_MAX = 133

} VNGErrCode;


// VNG_ErrMsg
//
//  Copies a zero terminated string that describes the error type to *msg.
//
//    VNGERR_INVALID_LEN - msg was null and msgLen was not 0,
//                         or msgLen was was not 0 and
//                         not long enough for msg.
//
//  If msg is not NULL and msgLen is not 0, the zero terminated
//  portion of the msg that fits will be copied to *msg.
//
//    VNGERR_NOT_FOUND   - errcode did not correspond to a valid
//                         VNGErrCode between VNG_OK and VNGERR_MAX
//                         non-inclusive.  msg[0] will be set to '\0'.
//
LIBVNG_API  VNGErrCode  VNG_ErrMsg (VNGErrCode  errcode,
                                    char       *msg,
                                    size_t      msgLen);


//-----------------------------------------------------------
//                  Basic types
//-----------------------------------------------------------


typedef uint16_t VNGPort;

typedef uint32_t VNGGameId;
typedef uint64_t VNGTitleId;
typedef int32_t  VNGDeviceType;


//
// VNGMillisec is a signed 32-bit integer that represents
// a duration of time with milliseconds resolution.
//
typedef int32_t      VNGMillisec;


// Many VNG functions accept a time-out parameter.   Normally the
// time-out determines the maximum time the function can wait before
// some data is available.   However, if the time-out value equals
// VNG_NOWAIT and no data is available, the function returns
// VNGERR_NOWAIT immediately.  If the time-out value equals VNG_WAIT,
// the function does not return until some data is available or an
// error conditiion is detected.  All functions that are waiting for data
// will return VNGERR_Fini if VNG_Fini is called in a different thread.
//
typedef VNGMillisec  VNGTimeout;

enum {
    VNG_NOWAIT = 0,
    VNG_WAIT   = INT32_MAX
};


// VNGTime is a signed 32-bit integer with milliseconds
// resolution that is used as a relative timestamp.
// A VNGTime value is the elapsed time since vng initialization.
// The time base is maintained internally by VNG.  VNGTime
// values are used to provide event timestamps in data returned
// by VNG APIs and internally by VNG.
//
typedef int32_t VNGTime;


// VNGTimeOfDay is a 64-bit unsigned integer with milliseconds resolution.
// It is used to represent absolute clock time.   Following the POSIX
// convention, VNGTimeOfDay is relative to 00:00:00.0 January 1, 1970.
//
typedef uint64_t VNGTimeOfDay;








//-----------------------------------------------------------
//---------------- Data Structures
//-----------------------------------------------------------


// The VNG library can connect to one VNG server at a time.
// The housekeeping information is kept in the VNG data structure.
//
// The fields inside the VNG structure should not be directly accessed.
//
typedef struct __VNG   VNG;


// When a Virtual Network (VN) is created, the housekeeping
// information is kept in a VN data structure.
//
// The fields inside the VN structure should not be directly accessed.
//
typedef struct __VN VN;


// A virtual network is uniquely identified by a VNId. The
// device ID is used to distinguish virtual networks created in a
// LAN environment.
//
typedef struct {
   uint64_t     deviceId;
   uint32_t     netId;
} VNId;


// A user is uniquely identified by a unique 32-bit VNGUserId.  The 
// VNGUserInfo structure maps the unique key VNGUserId to the login 
// name (an ASCII character string), and the nickname (a UTF-8 character 
// string).   Nickname can hold internationalized characters and 
// is used for display purposes.

typedef uint32_t VNGUserId;

#define VNG_INVALID_USER_ID  0


// The max length of a login name excluding the terminating '\0' is
// VNG_MAX_LOGIN_LEN.  The size of a char buf to hold a zero terminated
// login name is VNG_LOGIN_BUF_SIZE.
//
#define VNG_MAX_LOGIN_LEN     31
#define VNG_MAX_PASSWD_LEN    31
#define VNG_MAX_NICKNAME_LEN  31
#define VNG_MAX_DESCRIPTION_LEN  15
#define VNG_MAX_USER_ATTRIBUTES   8

#define VNG_LOGIN_BUF_SIZE       (VNG_MAX_LOGIN_LEN + 1)
#define VNG_PASSWD_BUF_SIZE      (VNG_MAX_PASSWD_LEN + 1)
#define VNG_NICKNAME_BUF_SIZE    (VNG_MAX_NICKNAME_LEN + 1)
#define VNG_DESCRIPTION_BUF_SIZE (VNG_MAX_DESCRIPTION_LEN+1)


//  Human-readable information of the UserId
//    
typedef struct {
   VNGUserId     uid;
   char 	 login[VNG_LOGIN_BUF_SIZE];
   char          nickname[VNG_NICKNAME_BUF_SIZE];
   char          description[VNG_DESCRIPTION_BUF_SIZE];
   int32_t       attrCount;
   int32_t       userAttr[VNG_MAX_USER_ATTRIBUTES];
} VNGUserInfo;


// Information gathered at game registration time
//
#define VNG_MAX_GAME_ATTR       16
#define VNG_GAME_KEYWORD_LEN    32
#define VNG_GAME_COMMENTS_LEN  256

#define VNG_GAME_PUBLIC          0
#define VNG_GAME_PRIVATE         1
#define VNG_GAME_INVITEONLY      2

typedef struct {
   VNId          vnId;
   VNGUserId     owner;
   VNGGameId     gameId;
   VNGTitleId    titleId;
   int32_t       netZone;
   int32_t       maxLatency;  // RTT in ms
   int16_t       accessControl;  // who can join this game
   int16_t       totalSlots;
   int16_t       buddySlots;
   int16_t       attrCount;     // number of defined attributes
   char          keyword[VNG_GAME_KEYWORD_LEN];
   int32_t       gameAttr[VNG_MAX_GAME_ATTR];
} VNGGameInfo;


// The fields inside VNGGameInfo do not change after registration.
// The fields inside VNGGameStatus changes and reflects the current
// status of the game.  The fields are gameStatus and numPlayers.

// The current status of the game
//
typedef struct {
   VNGGameInfo   gameInfo;
   uint32_t      gameStatus;
   uint32_t      numPlayers;
} VNGGameStatus;




//-----------------------------------------------------------
//----- Registration, server connection, and logon
//-----------------------------------------------------------


// Initialize VNG instance.
//   * vng:     the VNG session data structure
//
LIBVNG_API  VNGErrCode  VNG_Init (VNG *vng);


// Terminate VNG
//   - the VNG buffer can be freed after VNG_Fini returns.
//
LIBVNG_API  VNGErrCode  VNG_Fini (VNG *vng);



// Login types
//
enum {
  VNG_NOT_LOGIN = 0,
  VNG_USER_LOGIN,
  VNG_DEVICE_LOGIN,
};

#define VNG_DEF_SERVER_NAME    "vngs.idc.ique.com"
#define VNG_DEF_SERVER_PORT    16978

#define VNG_MAX_SERVER_NAME_LEN    255
#define VNG_SERVER_NAME_BUF_SIZE  (VNG_MAX_SERVER_NAME_LEN + 1)


// VNG_Login()
//   vng:          the VNG session data structure
//   serverName:   the fully qualified domain name of the VNG server
//   serverPort:   IP port of the VNG server application
//
// Login using the given loginName and passwd. If the user is already
// logged on the user will be logged off and back on again.  If the
// login fails or cannot be completed within the given time-interval,
// a suitable error code indicating the problem will be returned:
//
//   VNGERR_TIMEOUT        : Timeout before service could complete
//   VNGERR_INVALID_LOGIN  : The login name or passwd is not valid
//
LIBVNG_API  VNGErrCode  VNG_Login (VNG        *vng,
                                   const char *serverName,
                                   VNGPort     serverPort,
                                   const char *loginName,
                                   const char *passwd,
                                   VNGTimeout  timeout);

// Whenever the login session is terminated other than by calling
// VNG_Logout, a VNG_EVENT_LOGOUT event is sent to the application.

LIBVNG_API  VNGErrCode  VNG_Logout (VNG        *vng,
                                    VNGTimeout  timeout);

// Returns the current loginType
//
LIBVNG_API  int32_t  VNG_GetLoginType (VNG *vng);


// Once logged into the VNG infrastructure, personalized information
// may be accessed.   The VNGUserId might be accessed using
// VNG_MyUserId().   The nickname for this subscriber may be accessed
// using VNG_GetUserInfo().
//
// VNG_MyUserId returns the VNGUserId of the logged in user
//
//      VNG_INVALID_USER_ID if not logged in
//
LIBVNG_API  VNGUserId  VNG_MyUserId (VNG *vng);


// VNG_Register()
//   vng:          the VNG session data structure
//   serverName:   the fully qualified domain name of the VNG server
//   serverPort:   IP port of the VNG server application
//
// Register the device and returns an assigned loginName and passwd.
//
//
LIBVNG_API  VNGErrCode  VNG_Register(VNG        *vng,
                                     const char *serverName,
                                     VNGPort     serverPort,
                                     char       *loginName,
                                     char       *passwd,
                                     VNGTimeout  timeout);


// Change Password
//      VNGERR_NOT_LOGGED_IN : VNG user is not logged in
//      VNGERR_INVALID_ARG   : oldPasswd or newPasswd is NULL, zero size,
//                             or longer than VNG_MAX_PASSWD_LEN.
//      VNGERR_TIMEOUT       : Server didn't respond within timeout
//
LIBVNG_API VNGErrCode VNG_SetPassword(VNG        *vng,
                                      const char *oldPasswd,
                                      const char *newPasswd,   
                                      VNGTimeout  timeout);
 

// VNG_GetUserInfo retrieves VNGUserInfo from the VNG infrastructure server.
//
//      VNGERR_NOT_LOGGED_IN : VNG user is not logged in
//      VNGERR_INVALID_ARG   : uinfo is NULL
//      VNGERR_NOT_FOUND     : user info for uid was not found
//      VNGERR_TIMEOUT       : Server didn't respond within timeout
//
LIBVNG_API  VNGErrCode  VNG_GetUserInfo (VNG         *vng,
                                         VNGUserId    uid,
                                         VNGUserInfo *uinfo,  // out
                                         VNGTimeout   timeout);


//
LIBVNG_API  VNGErrCode  VNG_UpdateUserInfo(VNG               *vng,     
                                           const VNGUserInfo *uinfo,   
                                           VNGTimeout         timeout);


// VNG_ConnectStatus() bit masks
#define VNG_ST_USB_CONNECTED        0x02
#define VNG_ST_PROXY_CONNECTED      0x04
#define VNG_ST_ADHOC_SUPPORTED      0x08
#define VNG_ST_GATEWAY_DEFINED      0x10
#define VNG_ST_VNG_INITIALIZED      0x10000
#define VNG_ST_USER_LOGIN           0x20000
#define VNG_ST_DEVICE_LOGIN         0x40000
#define VNG_ST_RM_OK                0x80000


// VNG_ConnectStatus() returns connection status information
//
// if !(returned & VNG_ST_RM_OK)
//    Status is not available due to unexpected system error
//
// if !(returned & VNG_ST_VNG_INITIALIZED)
//    either *vng is not an initialized VNG or
//    VNG_Fini() has been called for the VNG or
//    VNG_ST_RM_OK is not set due to unexpected system error.
//
// if !(returned & VNG_ST_ADHOC_SUPPORTED),
//    matchmaking on an adhoc network is not available.
//
// If !(returned & VNG_ST_GATEWAY_DEFINED),
//    an internet connection is not available.
//
// If user login is active,
//    (returned & VNG_ST_USER_LOGIN) will be non-zero.
//
// If connection to the VNG Infrastructure server is lost, login will
// not be active and (returned & VNG_ST_USER_LOGIN) will be zero.
//
LIBVNG_API  uint32_t  VNG_ConnectStatus (VNG *vng);


//-----------------------------------------------------------
//-------------------Buddy List and Status
//-----------------------------------------------------------


// Personalized account details include a buddy list of other subscribers
// with whom the logged in client prefers to play games with.
// VNG_GetBuddyList() retrieves a players buddy list from the VNG server.
//

// Obtain a copy of the buddy list
//
LIBVNG_API  VNGErrCode  VNG_GetBuddyList (VNG          *vng,
                                          uint32_t      skipN, // skip N records
                                          VNGUserInfo  *userInfo,
                                          uint32_t     *nBuddies,
                                          VNGTimeout    timeout);


// After the subscriber is logged in, the following interface provides
// a means for the game application to manipulate the buddy list.
//
LIBVNG_API  VNGErrCode  VNG_InviteUser (VNG         *vng,
                                        const char  *loginName,
                                        VNGTimeout   timeout);

LIBVNG_API  VNGErrCode  VNG_AcceptUser (VNG         *vng,
                                        VNGUserId    uid,
                                        VNGTimeout   timeout);

LIBVNG_API  VNGErrCode  VNG_RejectUser (VNG         *vng,
                                        VNGUserId    uid,
                                        VNGTimeout   timeout);

LIBVNG_API  VNGErrCode  VNG_BlockUser (VNG         *vng,
                                       VNGUserId    uid,
                                       VNGTimeout   timeout);

LIBVNG_API  VNGErrCode  VNG_UnblockUser (VNG        *vng,
                                         VNGUserId   uid,
                                         VNGTimeout  timeout);


LIBVNG_API  VNGErrCode  VNG_RemoveUser (VNG        *vng,
                                        VNGUserId   uid,
                                        VNGTimeout  timeout);



// Buddy online status
//
typedef enum {
   VNG_STATUS_ONLINE,
   VNG_STATUS_OFFLINE,
   VNG_STATUS_AWAY,
   VNG_STATUS_GAMING,
   VNG_STATUS_INVITE_SENT,
   VNG_STATUS_INVITE_RECEIVED,
   VNG_STATUS_BLOCKED_FRIEND,
   VNG_STATUS_BLOCKED_STRANGER
} VNGUserOnlineStatus;




// Buddy status
typedef struct {
   VNGUserId             uid;
   VNGUserOnlineStatus   onlineStatus;
   VNGGameId             gameId;
   VNId                  vnId;
} VNGBuddyStatus;


// Update user's own status
//
LIBVNG_API  VNGErrCode  VNG_UpdateStatus (VNG                  *vng,
                                          VNGUserOnlineStatus  status,
                                          VNGGameId            gameId,
                                          VNId                 vnId,
                                          VNGTimeout           timeout);


// Obtain the state of the buddies
//
LIBVNG_API  VNGErrCode  VNG_GetBuddyStatus (VNG            *vng,
                                            VNGBuddyStatus *buddyStatus,
                                            uint32_t        nBuddies,
                                            VNGTimeout      timeout);


// Enable/Disable tracking of buddy state changes
//   EnableBuddyList downloads the buddy list from the VNG server
//   After that, the VNG server pushes changes to the VNG client.
//   Buffer used to track buddy list is allocated by the app.
//

typedef enum {
   VNG_DATA_BUDDYSTATUS,
} VNGData;

LIBVNG_API  VNGErrCode  VNG_EnableTracking (VNG         *vng,
                                            VNGData      dataType,
                                            VNGTimeout   timeout);


LIBVNG_API  VNGErrCode  VNG_DisableTracking (VNG         *vng,
                                             VNGData      dataType,
                                             VNGTimeout   timeout);





//-----------------------------------------------------------
//--------------------- Details of the Games
//-----------------------------------------------------------


// Update status about one game.
//
LIBVNG_API  VNGErrCode  VNG_UpdateGameStatus (VNG            *vng,
                                              VNId            vnId,
                                              uint32_t        gameStatus,
                                              uint32_t        numPlayers,
                                              VNGTimeout      timeout);


// Obtain status about one or more games.  The VNid of the games are
// obtained from gameStatus[*].gameInfo.vnId.
//
LIBVNG_API  VNGErrCode  VNG_GetGameStatus (VNG            *vng,
                                           VNGGameStatus  *gameStatus,
                                           uint32_t        nGameStatus,
                                           VNGTimeout      timeout);


LIBVNG_API  VNGErrCode  VNG_GetGameComments (VNG        *vng,
                                             VNId        vnId,
                                             char       *comments,
                                             size_t     *commentSize,
                                             VNGTimeout  timeout);


//-----------------------------------------------------------
//--------------------- VN Creation
//-----------------------------------------------------------


// Specify VN (game session) policy
//    VN_ABORT_ON_ANY_EXIT:  VN terminates if any member exits
//    VN_ABORT_ON_HOST_EXIT: VN terminates if owner exits
//    VN_AUTO_ACCEPT_JOIN:   automatically accept join requests
//

#define VN_ABORT_ON_ANY_EXIT    0x00000001
#define VN_ABORT_ON_OWNER_EXIT  0x00000002
#define VN_AUTO_ACCEPT_JOIN     0x00000004
#define VN_ANY                  0x40000000  // reserved for internal VNG use

#define VN_DEFAULT_POLICY   (VN_ABORT_ON_OWNER_EXIT | VN_AUTO_ACCEPT_JOIN)

typedef uint32_t VNPolicies;




// Specify domain of the game VN
// VN_DOMAIN_LOCAL:  A VN of this domain allows a game application
//                   to take advantage of the VNG Inter-process
//                   communication primitives within the application.
//                   It does not support communications over LAN or Internet.
// VN_DOMAIN_ADHOC:  A VN of this domain allows two or more game
//                   consoles connected together  without the help
//                   of the infrastructure servers.
// VN_DOMAIN_INFRA:  An infrastructure providing search and matchmaking
//                   functions is involved. A VN of this domain can be
//                   registered to the infrastructure.   Other clients
//                   can search for and join this VN without knowing its
//                   IP address, and the infrastructure assists with the
//                   opening of firewall ports.
//
typedef enum {
    VN_DOMAIN_LOCAL = 1,
    VN_DOMAIN_ADHOC = 2,
    VN_DOMAIN_INFRA = 3,
} VNDomain;


// Specify virtual network class
//
// Class 1   256 million networks, max  4 members each
// Class 2    64 million networks, max 16 members each  (default)
// Class 3    16 million networks, max 64 members each
// Class 4   16384 networks, max 65536 members each
//
// For class 1, 2, and 3, the entry and exit of a new VN member
// are automatically distributed to every node in the VN (as VNG events).
// Every node can communicate with any other node.
//
// For class 4,  the overhead of maintaining a complete connected
// network is too high. So a VN can only communicate with the game host.
// Class 4 is for implementation of MMOGs.
//
// VN_CLASS_4 is a future feature and is not currently available.
// VNGERR_NOT_SUPPORTED will be returned by VNG_NewVN() for class 4.
//
typedef enum {
    VN_CLASS_1,
    VN_CLASS_2,
    VN_CLASS_3,
    VN_CLASS_4,

    VN_DEFAULT_CLASS = VN_CLASS_2

} VNClass;



// Create a new game VN (could be used offline)
// The game VN data structure vn is allocated
// by the application.
//
LIBVNG_API  VNGErrCode  VNG_NewVN (VNG       *vng,
                                   VN        *vn,
                                   VNClass    vnClass,
                                   VNDomain   domain,
                                   VNPolicies policies);

// Delete a game VN.
// Only the VN Host can delete a VN.  Any member can exit, which may
// also cause the VN to be automatically deleted based on VN policies.
// Error codes may be:
//
//   VNGERR_UNREACHABLE : The peer/server cannot be reached
//   VNGERR_VN_NOT_HOST : Caller is not the host of the VN
//
LIBVNG_API  VNGErrCode  VNG_DeleteVN (VNG *vng, VN *vn);


// Inialize *vn  from *vnToClone.
//
// vn will represent the same VN as the vnToClone.
//
// This is usefull to pass a VN from one process to another.
//
// This is not usefull on LINUX or WIN32 as each LINUX or WIN32
// process has its own private VNG environment.
//
LIBVNG_API  VNGErrCode VNG_CloneVN (VNG *vng,
                                    VN  *vn,           /* w */
                              const VN  *vnToClone);   /* r */


// Get all VNs with state VN_OK
//
// Initializes an array of VNs at *vns as clones of existing VNs.
//
// If nVNs is less than or equal to the number of VNs, all VNs are
// returned at *vns and *nVNs is set to the number of VNs returned.
//
// If there are more VNs than can be returned at *vns, VNG_GetVNs()
// initializes the number of VNs specified by *nVNs, sets *nVNs to
// the total number of active VNs, and returns VNGERR_OVERFLOW.
//
// The error return must be checked as the return value at *nVNs may
// be greater than then the original value.
//
// The number of active VNs can be found without returning any VNs,
// by passing 0 at *nVNs.
//
// If nVNs is NULL, VNGERR_INVALID_ARG is returned.
//
// If *nVNs is not 0 and vns is NULL, VNGERR_INVALID_LEN
// is returned.
//
LIBVNG_API  VNGErrCode VNG_GetVNs (VNG       *vng,
                                   VN        *vns,
                                   uint32_t  *nVNs);



//-----------------------------------------------------------
//                  Game Registration
//-----------------------------------------------------------


// Register a new peer-to-peer game-session for matchmaking purposes.
//
//   VNGERR_TIMEOUT       : Timeout before service could complete
//   VNGERR_NOT_LOGGED_IN : Requires user to be logged in
//
LIBVNG_API  VNGErrCode  VNG_RegisterGame (VNG          *vng,
                                          VNGGameInfo  *info,
                                          char         *comments,
                                          VNGTimeout    timeout);

//  Unregister a game session
//     The session might still be active, but it is not searchable
//
LIBVNG_API  VNGErrCode  VNG_UnregisterGame (VNG            *vng,
                                            VNId            vnId,
                                            VNGTimeout      timeout);






//-----------------------------------------------------------
//                  Joining and leaving a VN
//-----------------------------------------------------------


// Update the VN object, or return a denial reason
// if the request was denied (VNGERR_VN_JOIN_DENIED) by the vn owner
// or the VNG infrastructure.  When other errors occur NULL
// is returned and no denial reason given.
//
// The request will be passed on to the owner of the VN if the
// VN policy is not VN_AUTO_ACCEPT_JOIN.
//
//   VNGERR_TIMEOUT          : Timeout before connection to vn owner
//   VNGERR_UNREACHABLE      : The owner/server cannot be reached to
//                                accept/deny the attempt to join
//   VNGERR_VN_JOIN_DENIED   : owner/server denied a join request
//
// The VNId may represent a peer-to-peer gaming session
// or may be a VN that is used for a game specific purpose
// other then the VN registered for match making.
//

#define VNG_MAX_JOIN_REQ_MSG_LEN    1023  /* not including terminating zero */
#define VNG_JOIN_REQ_MSG_BUF_SIZE  (VNG_MAX_JOIN_REQ_MSG_LEN + 1)

#define VNG_MAX_JOIN_DNY_MSG_LEN    1023  /* not including terminating zero */
#define VNG_JOIN_DNY_MSG_BUF_SIZE  (VNG_MAX_JOIN_DNY_MSG_LEN + 1)

LIBVNG_API  VNGErrCode  VNG_JoinVN (VNG         *vng,        // in
                                    VNId         vnId,       // in
                                    const char  *msg,        // in
                                    VN          *vn,         // out
                                    char        *denyReason, // out
                                    size_t       denyReasonLen, // in
                                    VNGTimeout   timeout);


// VNG_GetJoinRequest
//
// A blocking call for receiving incoming join requests.  For
// non-blocking behavior set the timeout to VNG_NOWAIT.
//
// Returns VNGERR_TIMEOUT and a NULL vn pointer when no request is
// received within the timeout period.
//
// Returns VNGERR_INVALID_VN and a NULL vn pointer if waiting for
// requests for a specific vnId and the associated VN has exited.
//
LIBVNG_API  VNGErrCode  VNG_GetJoinRequest (VNG         *vng,
                                            VNId         vnId, // in
                                            VN         **vn,   // out
                                            uint64_t    *requestId,
                                            VNGUserInfo *userInfo,
                                            char        *joinReason,
                                            size_t       joinReasonLen,
                                            VNGTimeout   timeout);


// Responding to the request
//
LIBVNG_API  VNGErrCode  VNG_AcceptJoinRequest (VNG        *vng,
                                               uint64_t    requestId);

LIBVNG_API  VNGErrCode  VNG_RejectJoinRequest (VNG        *vng,
                                               uint64_t    requestId,
                                               const char *reason);


//  Leave the virtual network
//    If VN_ABORT_ON_OWNER_EXIT is set and the node is the owner,
//    then the VN is destroyed.
//    If VN_ABORT_ON_ANY_EXIT is set, then the VN is destroyed.
//
LIBVNG_API  VNGErrCode  VNG_LeaveVN (VNG *vng, VN *vn);






//-----------------------------------------------------------
//                  Invitation to Join a Virtual Network
//-----------------------------------------------------------

// Invite a number of users
//

#define VNG_MAX_NOTIFY_MSG_BUF_SIZE    512

LIBVNG_API  VNGErrCode  VNG_SendNotification (VNG          *vng,          // in
                                              VNGUserId    *uid,          // in
                                              uint32_t      nUsers,       // in
                                              const char   *message,      // in
					      size_t        messageLen);  // in

// Get outstanding invitation
//
LIBVNG_API  VNGErrCode  VNG_RecvNotification(VNG          *vng,        // in
                                             VNGUserInfo  *userInfo,   // out
                                             char         *message,    // out
                                             size_t       *messageLen, // in/out
                                             VNGTimeout    timeout);




//-----------------------------------------------------------
//              VN: Accessing Virtual Network Information
//-----------------------------------------------------------


// A member of a virtual network is identified by a VNMember ID.
// A VNMember ID is unique for the associated VN,
// but is not unique across multiple VNs.
//
typedef uint16_t VNMember;



// VN Network State
//
typedef enum {
    VN_EXITED  = 0,
    VN_OK      = 1,

} VNState;




// Network nodes and state
//

// VN_Self returns the VNMember ID for self
//
//      VN_MEMBER_INVALID if the vn is no longer valid
//
LIBVNG_API  VNMember  VN_Self (VN *vn);


// VN_Owner returns the VNMember of the owner of the vn
//
//      VN_MEMBER_INVALID if the vn is no longer valid
//
LIBVNG_API  VNMember  VN_Owner (VN *vn);


// VN_State returns the state of the virtual network
//
LIBVNG_API  VNState  VN_State (VN *vn);


// Accessing the participants in a VN as members.
//
// VN_NumMembers() returns the number of nodes in the VN network.
//
LIBVNG_API  uint32_t  VN_NumMembers (VN *vn);


// VN_GetMembers() stores up to nMembers of the current set of vn members
// into the array indicated by the members argument.
//
// Returns the total number of current vn members which may be
// larger than nMembers.
//
LIBVNG_API  uint32_t  VN_GetMembers (VN       *vn,
                                     VNMember *members,
                                     uint32_t  nMembers);


// VN member information
//


// VN_GetMemberState
//
//      VNG_OK             if memb is member of vn
//      VNGERR_NOT_FOUND   if memb is not member of vn
//      other VNGErrCodes  if appropriate
//
LIBVNG_API  VNGErrCode  VN_MemberState (VN *vn, VNMember memb);


// VN_MemberUserId
//
//      VNG_INVALID_USER_ID  memb is not logged in to the infrastructure
//                           or is not a member of the vn
//                           or the vn is not valid
//
LIBVNG_API  VNGUserId  VN_MemberUserId (VN        *vn,
                                        VNMember   memb,
                                        VNGTimeout timeout);

// VN_GetMemberLatency
//
//      VN_MEMB_LATENCY_NA returned if memb latency is not available
//
#define VN_MEMB_LATENCY_NA  (-1)

LIBVNG_API  VNGMillisec  VN_MemberLatency (VN *vn, VNMember memb);


#define VNG_INVALID_DEV_TYPE   (-1)

// VN_MemberDeviceType
//
//      VNG_INVALID_DEV_TYPE  member device type is not available
//
LIBVNG_API  VNGDeviceType  VN_MemberDeviceType (VN *vn, VNMember memb);

// VN_GetVNId
//
// If VNG_OK is returned, *vnId will be the VNId of the vn
// The vnId pointer must be provided by the caller.
//
//     VNGERR_INVALID_VN if the vnId can not be determined
//
LIBVNG_API  VNGErrCode  VN_GetVNId (VN *vn, VNId *vnId);







//-----------------------------------------------------------
//                  VN Peer-to-Peer Communication
//-----------------------------------------------------------


// The maximum bytes that can be sent in a single
// peer-to-peer message, request, response, RPC args, or RPC ret.
#define VN_MAX_MSG_LEN   (15*1024)


typedef uint32_t VNServiceType;
typedef uint32_t VNServiceTypeSet;

#define  VN_SERVICE_TYPE_ANY               0
#define  VN_SERVICE_TYPE_UNRELIABLE_MSG    1
#define  VN_SERVICE_TYPE_RELIABLE_MSG      2
#define  VN_SERVICE_TYPE_REQUEST           3
#define  VN_SERVICE_TYPE_RESPONSE          4
#define  VN_SERVICE_TYPE_MAX               4

#define VN_SERVICE_TYPE_UNRELIABLE_MSG_MASK (1<<VN_SERVICE_TYPE_UNRELIABLE_MSG)
#define VN_SERVICE_TYPE_RELIABLE_MSG_MASK   (1<<VN_SERVICE_TYPE_RELIABLE_MSG)
#define VN_SERVICE_TYPE_REQUEST_MASK        (1<<VN_SERVICE_TYPE_REQUEST)
#define VN_SERVICE_TYPE_RESPONSE_MASK       (1<<VN_SERVICE_TYPE_RESPONSE)

#define VN_SERVICE_TYPE_ANY_MASK (   VN_SERVICE_TYPE_UNRELIABLE_MSG_MASK \
                                   | VN_SERVICE_TYPE_RELIABLE_MSG_MASK   \
                                   | VN_SERVICE_TYPE_REQUEST_MASK        \
                                   | VN_SERVICE_TYPE_RESPONSE_MASK)

// VN_SERVICE_TAG_ANY can be specified for the serviceTag arg
// of VN_SendMsg(), VN_RecvMsg(), VN_RecvReq().
// It is not allowed for VN_RegisterRPCService() or VN_RecvResp
// and therefore is not useful for VN_SendRPC() or VN_SendResp

#define VN_SERVICE_TAG_ANY    0xFFFF

#define VN_SERVICE_TAG_MAX    0xFFFE
#define VN_SERVICE_TAG_MIN    0


typedef uint16_t          VNServiceTag;
typedef uint16_t          VNCallerTag;
typedef uint16_t          VNAttr;

typedef struct {
        VN            *vn;
        VNMember       sender;          // Never a VNMember constant
        VNMember       receiver;        // always VN_Self(vn)
        VNServiceType  serviceType;
        VNServiceTag   serviceTag;
        int32_t        optData;         // small optional data
        VNAttr         attr;            // transfer attribute
        int16_t        payloadSize;     // payload size
        VNCallerTag    callerTag;       // optional caller tag
        VNGTime        sendTimestamp;   // optional timestamp
} VNMsgHdr;


// VN_Attr allows delivery of optional data in the message headers,
// e.g., timestamp, or the altering of delivering mode.

enum {
        VN_ATTR_UNRELIABLE = 0x1,   // default is reliable
        VN_ATTR_TIMESTAMP  = 0x2,   // default is no timestamp
        VN_ATTR_NOENCRYPT  = 0x4,   // default is with encryption
};

#define VN_DEFAULT_ATTR  0


// The receiver of communication data is usually specified by a
// VNMember parameter.  A set of pre-defined VNMember constants
// allow the VNMember argument to be used for broadcast
// communications when sending and reception from any sender when
// receiving.

//      VN_MEMBER_SELF      -  member VN_Self(vn)
//      VN_MEMBER_OWNER     -  member VN_Owner(vn)
//      VN_MEMBER_OTHERS    -  all members except self
//      VN_MEMBER_ALL       -  all members including self
//      VN_MEMBER_ANY       -  any member  including self
//      VN_MEMBER_INVLAID   -  used in returned VNMember values
//                             when can't reutrn valid VNMember
//
// NOTE: VN_MEMBER_ALL and VN_MEMBER_ANY are the same value

enum {
    VN_MEMBER_SELF     =  _VNG_VN_MEMBER_SELF,
    VN_MEMBER_OWNER    =  _VNG_VN_MEMBER_OWNER,
    VN_MEMBER_OTHERS   =  _VNG_VN_MEMBER_OTHERS,
    VN_MEMBER_ALL      =  _VNG_VN_MEMBER_ALL_OR_ANY,
    VN_MEMBER_ANY      =  _VNG_VN_MEMBER_ALL_OR_ANY,
    VN_MEMBER_INVALID  =  _VNG_VN_MEMBER_INVALID,
};



// Block until there is incoming data on one or more of the given
// service channels from the given VN member, or until the timeout
// expires, and return which service channels there is data on if
// any.  Error codes may be:
//
//   VNGERR_TIMEOUT     : Timeout before any input on service channel
//   VNGERR_UNREACHABLE : The peer/server cannot be reached
//
LIBVNG_API  VNGErrCode  VN_Select (VN               *vn,
                                   VNServiceTypeSet  selectFrom,
                                   VNServiceTypeSet *ready,
                                   VNMember          memb,
                                   VNGTimeout        timeout);


// Send tagged message to another VN member
//
//   VNGERR_UNREACHABLE : Failed to send to the given member.
//   VNGERR_BUF_FULL    : Send buffer was full and timeout was VNG_NOWAIT
//                        or msg could not be copied to send buffer
//                        before timeout expired.
//
LIBVNG_API  VNGErrCode  VN_SendMsg (VN            *vn,
                                    VNMember       memb,
                                    VNServiceTag   serviceTag,
                                    const void    *msg,
                                    size_t         msglen,
                                    VNAttr         attr,
                                    VNGTimeout     timeout);

// Receive any message matching the given dispatch tag from
// the specified VN member.  If timeout is VNG_NOWAIT the recv call
// returns immediately.  If timeout is VNG_WAIT the recv call does
// not return until a matching msg is received.  Otherwise, the
// call returns when a matching msg is recieved or the specified
// timeout has elapsed.
//
//   VNGERR_NOWAIT : No awaiting message matching the member
//                     and tag
//
LIBVNG_API  VNGErrCode  VN_RecvMsg (VN           *vn,
                                    VNMember      memb,
                                    VNServiceTag  serviceTag,
                                    void         *msg,
                                    size_t       *msglen,
                                    VNMsgHdr     *hdr,
                                    VNGTimeout    timeout);


//-----------------------------------------------------------
//                  VN SERVICE REQUEST
//-----------------------------------------------------------

// Send tagged request to a particular virtual network
//
// Returns callerTag that is passed to VN_RecvResp() to identify
// the response to the specific call to VN_SendReq()
//
// The passed optData will be present in the VNMsgHdr passed
// back in the hdr arg of VN_RecvReq().
//
//   VNGERR_UNREACHABLE : Failed to send to the given member
//   VNGERR_BUF_FULL    : Send buffer was full and timeout was VNG_NOWAIT
//                        or msg could not be copied to send buffer
//                        before timeout expired.
//
LIBVNG_API  VNGErrCode  VN_SendReq (VN           *vn,
                                    VNMember      memb,
                                    VNServiceTag  serviceTag,  // function id
                                    VNCallerTag  *callerTag,
                                    const void   *msg,
                                    size_t        msglen,
                                    int32_t       optData,
                                    VNGTimeout    timeout);

// Receive any request matching the given dispatch tag from a
// particular virtual network member.  The recv call returns immediately
// if timeout equals NOWAIT, or returns when a matching request is
// received or the timeout expires.
//
//   VNGERR_NOWAIT : No awaiting request matching the member
//                     and tag
//
LIBVNG_API  VNGErrCode  VN_RecvReq (VN           *vn,
                                    VNMember      memb,
                                    VNServiceTag  serviceTag,
                                    void         *msg,
                                    size_t       *msglen,
                                    VNMsgHdr     *hdr,
                                    VNGTimeout    timeout);






//-----------------------------------------------------------
//                  VN SERVICE RESPONSE
//-----------------------------------------------------------

// Send response to a virtual network member
//
//   VNGERR_UNREACHABLE : Failed to send to the given member
//   VNGERR_BUF_FULL    : Send buffer was full and timeout was VNG_NOWAIT
//                        or msg could not be copied to send buffer
//                        before timeout expired.
//
LIBVNG_API  VNGErrCode  VN_SendResp (VN           *vn,
                                     VNMember      memb,
                                     VNServiceTag  serviceTag,
                                     VNCallerTag   callerTag,
                                     const void   *msg,
                                     size_t        msglen,
                                     int32_t       optData,
                                     VNGTimeout    timeout);

// Receive any response matching the given dispatch tag from a
// particular VN member.
// callertag is the callerTag returned from the sendReq call.
// Returns msg, msglen, hdr for the received response.
//
//   VNGERR_NOWAIT : No awaiting response matching the member/tag
//
LIBVNG_API  VNGErrCode  VN_RecvResp (VN           *vn,
                                     VNMember      memb,
                                     VNServiceTag  serviceTag,
                                     VNCallerTag   callerTag,
                                     void         *msg,
                                     size_t       *msglen,
                                     VNMsgHdr     *hdr,
                                     VNGTimeout    timeout);





//-----------------------------------------------------------
//                  VN RPC
//-----------------------------------------------------------

// We implement remote procedure calls by registering the
// procedures with a virtual network.  The procedures remain in
// effect for the duration of the VN and take as input:
//
//   vn:     The VN to which it applies
//   hdr:    The transmission header for the remote caller
//   args:   The transmitted arguments to the call as a blob
//   ret:    Where to put the data blob returned by the call
//   retLen: Where to return the size of the data stored at
//           ret.  A buffer of size VN_MAX_MSG_LEN is available
//           at ret.
//
// Before return, retLen must be set to the actual size of
// the return data blob (no more than VN_MAX_MSS_LEN).
//
typedef int32_t (*VNRemoteProcedure) (VN         *vn,
                                      VNMsgHdr   *hdr,
                                      const void *args,
                                      size_t      argsLen,
                                      void       *ret,
                                      size_t     *retLen);


LIBVNG_API  VNGErrCode  VN_RegisterRPCService (VN               *vn,
                                               VNServiceTag      procId,
                                               VNRemoteProcedure proc);

// Unregister RPC service
//  if procId is VN_SERVICE_TAG_ANY, then all RPC
//  functions are unregistered
//
LIBVNG_API  VNGErrCode  VN_UnregisterRPCService (VN               *vn,
                                                 VNServiceTag      procId);

// Call a remote procedure for the given session member. This
// always involves a two-way communication, and both directions
// must be successfully transmitted before this function returns.
// If the timeout expires before the response can be processed, or
// a communication error occurs, the call fails with one of the
// following error codes:
//
//    VNGERR_UNREACHABLE      : Failed to communicate with the member
//    VNGERR_VN_MISSING_PROC:   Failed to communicate with the member
//    VNGERR_TIMEOUT          : Failed to complete the RPC transaction
//
LIBVNG_API  VNGErrCode  VN_SendRPC (VN           *vn,
                                    VNMember      memb,
                                    VNServiceTag  serviceTag,
                                    const void   *args,
                                    size_t        argsLen,
                                    void         *ret,
                                    size_t       *retLen,
                                    int32_t      *optData,
                                    VNGTimeout    timeout);



// Process one RPC requests
//
LIBVNG_API  VNGErrCode  VNG_ServeRPC (VNG *vng, VNGTimeout timeout);





//-----------------------------------------------------------
//--------------------  VNG Matchmaking
//-----------------------------------------------------------



typedef enum {
   VNG_CMP_DONTCARE,
   VNG_CMP_STR,
   VNG_CMP_EQ,
   VNG_CMP_NEQ,
   VNG_CMP_LT,
   VNG_CMP_GT,
   VNG_CMP_LE,
   VNG_CMP_GE,

} VNGCompare;


//  Define the search criteria
//
#define VNG_MAX_PREDICATES   32

// masks used to specify search domain
#define VNG_SEARCH_LOCAL_MASK    0x01
#define VNG_SEARCH_ADHOC_MASK    0x02
#define VNG_SEARCH_INFRA_MASK    0x04

#define VNG_SEARCH_LOCAL        VNG_SEARCH_LOCAL_MASK
#define VNG_SEARCH_ADHOC       (VNG_SEARCH_ADHOC_MASK | VNG_SEARCH_LOCAL)
#define VNG_SEARCH_INFRA       (VNG_SEARCH_INFRA_MASK | VNG_SEARCH_ADHOC)

#define VNG_SEARCH_NOLOCAL     (VNG_SEARCH_INFRA_MASK | VNG_SEARCH_ADHOC_MASK)

typedef struct {
      uint32_t    cmp;     // VNGCompare
      uint32_t    attrId;
      uint32_t    attrValue;
} VNGSearchPredicate;


// For ad-hoc and local searches, gameId == 0 means find all
// joinable games that meet domain and maxLatency criteria
//
// When the search criteria domain includes the ifrastucture (i.e.
// VNG_SEARCH_INFRA_MASK), the gameId must be non-zero.

typedef struct {
   VNGGameId   gameId;     // must be non-zero for ifra searches.
   uint32_t    domain;     // masks defined above
   VNGMillisec maxLatency; // RTT in ms

   // Remaining members not referenced if gameId == 0
   uint32_t    cmpKeyword;
   char        keyword[VNG_GAME_KEYWORD_LEN];
   VNGSearchPredicate pred[VNG_MAX_PREDICATES];
} VNGSearchCriteria;


// Matchmaking.
//    skipN: skip the first N entries
//
LIBVNG_API  VNGErrCode  VNG_SearchGames (VNG                 *vng,
                                         VNGSearchCriteria   *searchCriteria,
                                         VNGGameStatus       *gameStatus,
                                         uint32_t            *nGameStatus,
                                         uint32_t             skipN,
                                         VNGTimeout           timeout);


// When the console is not connected to the infrastructure,
// the VNG_SearchGames() function can still be used to retrieve
// ad-hoc networked games. The default ad-hoc domain contains
// all servers in the LAN broadcast domain.
//
// THe VNG library periodically performs a broadcast discovery
// on the LAN to determine the available games.
//
// An additional ad-hoc game server, specified using its
// IP address and port, can be added to the ad-hoc domain
// using VNG_AddServerToAdhocDomain().
//
// VNG_SearchGames() will return the games registered on the ad-hoc
// servers, and the games located by broadcast discovery. The ad-hoc
// server list is cleared by invoking VNG_ResetAdhocDomain().
//
// To retrieve the list of all games in the adhoc domain,
// set the searchCriteria gameId to 0, domain to VNG_SEARCH_ADHOC,
// and maxLatency to a large value; or pass VNG_LIST_ADHOC_GAMES
// as the searchCriteria argument to VNG_SearchGames().

#define VNG_LIST_ADHOC_GAMES    (VNGSearchCriteria*)NULL




//  Add a game server to the ADHOC domain
//
LIBVNG_API  VNGErrCode  VNG_AddServerToAdhocDomain (VNG        *vng,
                                                   const char *serverName,
                                                   VNGPort     serverPort);
//  Clear the ad-hoc server list
//
LIBVNG_API  VNGErrCode  VNG_ResetAdhocDomain (VNG *vng);





//-----------------------------------------------------------
//                  Score Management
//-----------------------------------------------------------

#define VNG_SCORE_INFO_SIZE          16
#define VNG_MAX_SCORE_ITEMS          64
#define VNG_MAX_SCORE_RESULTS        50 
#define VNG_MAX_RANKED_SCORE_RESULTS 50 
#define VNG_MAX_SCORE_OBJ_SIZE       (1024*2) // 11/4th/2005 Game Demand 2K

// Score data structure
//

typedef struct {
   VNGUserId    uid;
   VNGTitleId   titleId;
   VNGGameId    gameId;
   uint32_t     slotId;
   uint32_t     scoreId;
} VNGScoreKey;


typedef struct {
   VNGUserInfo  uInfo;
   VNGTimeOfDay timeOfDay;
   uint32_t     nItems;   // number of score items
   uint32_t     objSize;  // 0 if there is no object
   uint8_t      info[VNG_SCORE_INFO_SIZE];
} VNGScore;


typedef struct {
   uint32_t     itemId;
   uint32_t     score;
   uint32_t     rank;     // not used during submission
} VNGScoreItem;



// VNG_SubmitScore also returns the ranking, so that the game can
// report the rankings to the subscriber.  The game can use
// the rankings to decide whether to upload the score object.
//
LIBVNG_API  VNGErrCode  VNG_SubmitScore (VNG          *vng,
                                         VNGScoreKey  *key,
                                         uint8_t       info[16],
                                         VNGScoreItem *scoreItems,
                                         uint32_t      nItems,
                                         VNGTimeout    timeout);


// Attach a large binary object to a previously submitted record.
//
LIBVNG_API  VNGErrCode  VNG_SubmitScoreObject (VNG         *vng,
                                               VNGScoreKey *objKey,
                                               const char  *object,
                                               size_t       objectSize,
                                               VNGTimeout   timeout);


// Get the score and score items matched with the ScoreKey specified
// in the VNGScore parameter.
//
//  VNGERR_TIMEOUT : Timeout before server request completed
//
LIBVNG_API  VNGErrCode  VNG_GetGameScore (VNG          *vng,
                                          VNGScoreKey  *scoreKey,
                                          VNGScore     *score,
                                          VNGScoreItem *scoreItems,
                                          uint32_t     *nItems,
                                          VNGTimeout    timeout);


// Retrieve the score object.
//
LIBVNG_API  VNGErrCode  VNG_GetGameScoreObject (VNG         *vng,
                                                VNGScoreKey *scoreKey,
                                                char        *object,
                                                size_t      *objectSize,
                                                VNGTimeout   timeout);


// Delete a game score and its object from the database
//
LIBVNG_API  VNGErrCode  VNG_DeleteGameScore (VNG          *vng,
                                             VNGScoreKey  *scoreKey,
                                             VNGTimeout    timeout);


// VNG_GetRankedScores() returns the score that matched the GameId,
// ScoreId and ItemId.
//
// If optUid or optDeviceId is non-zero, the returned record
// must also match the specified Uid and specified DeviceId.
//
typedef struct {
   VNGScoreKey  key;
   VNGScore     score;
   VNGScoreItem scoreItem;
} VNGRankedScoreResult;

LIBVNG_API  VNGErrCode  VNG_GetRankedScores (VNG          *vng,
                                             VNGGameId     gameId,
                                             uint32_t      scoreId,
                                             uint32_t      itemId,
                                             VNGUserId     optUid,
                                             uint32_t      rankBegin,
                                             VNGRankedScoreResult *scoreResult,
                                             uint32_t       *nResults,
                                             VNGTimeout      timeout);


// VNG_GetScoreKeys() provides a convenient way for a user (or device) 
// to locate the submitted score records.
// 
// It returns the records matched with Uid, GameId, and ScoreId.
// Uid must be specified.  GameId and ScoreId are optional.
//

LIBVNG_API VNGErrCode VNG_GetScoreKeys(VNG            *vng, 
                                       VNGUserId       uid,
                                       uint32_t        optGameId,
                                       uint32_t        optScoreId,
                                       VNGScoreKey    *scoreKeys,
                                       uint32_t       *nScoreKeys,
                                       VNGTimeout      timeout);


//-----------------------------------------------------------
//                  Voice
//-----------------------------------------------------------


#define VNG_VOICE_DISABLE 0
#define VNG_VOICE_ENABLE  1

// Activate voice
//
// If mem is VN_MEMBER_OTHERS, new VN members are
// automatically included in the voice broadcast.
//
// what can be VNG_VOICE_ENABLE or VNG_VOICE_DISABLE
//
LIBVNG_API VNGErrCode VNG_ActivateVoice(VN       *vn,
                                        int32_t   what,
                                        VNMember  mem);


#define VNG_VOL_SET       0
#define VNG_VOL_INCREMENT 1
#define VNG_VOL_DECREMENT 2

// Adjust voice volume
//
// what can be VNG_VOL_SET, VNG_VOL_INCREMENT, or VNG_VOL_DECREMENT
// volume is
//
LIBVNG_API VNGErrCode VNG_AdjustVolume(VNG     *vng,
                                       int32_t  what,
                                       int32_t  volume);


#define VNG_VOICE_CODEC_ADPCM16   0
#define VNG_VOICE_CODEC_ADPCM32   1

// Select codec
//
// The default codec is ADPCM16. VNG allows the application to select
// the codec.   Parameters of the codec, such as voice activation
// detection, jitter buffering, distribution topology are determined
// automatically.
//
LIBVNG_API VNGErrCode VNG_SelectVoiceCodec(VNG     *vng,
                                           int32_t  codec);




//-----------------------------------------------------------
//                  Stored Messages
//-----------------------------------------------------------

// VNG_MAX_SUBJECT_LEN does not include terminating '\0'
// VNG_SUBJECT_BUF_SIZE includes space for terminaing '\0'
#define VNG_MAX_SUBJECT_LEN      63
#define VNG_SUBJECT_BUF_SIZE    (VNG_MAX_SUBJECT_LEN + 1)

#define VNG_MAX_STORED_MSG_LEN  (30*2048)

// Maximum value allowed for nRecipients arg to VNG_StoreMessage
#define VNG_MAX_STORE_MSG_N_RECIP  100


// Stored Messages of type VNG_MEDIA_TYPE_TEXT have no embedded
// '\0' chars and are terminated at the first '\0' char.

#define VNG_MEDIA_TYPE_UNKNOWN    0
#define VNG_MEDIA_TYPE_TEXT       1
#define VNG_MEDIA_TYPE_VOICE      2


// VNG_StoreMessage() stores a message for retrieval by a list of recipients.
//
// recipients is an array of pointers to zero terminated login names.
//
// results[i] indicates if the msg was successfully stored for recipient[i].
//
// results[i] values:
//    VNG_OK                - successfully stored
//    VNGERR_INVALID_LOGIN  - Recipient not found or inactive account
//    VNGERR_MAILBOX_FULL   - Num received messages quota exceeded
//    VNGERR_INFRA_NS       - Non-specific fail to deliver
//    VNGERR_STM_SEND       - Msg was not stored because of send failure
//
// If the return value is not VNG_OK, all results[i] will be VNGERR_STM_SEND.
//
// VNG_StoreMessage() specific error return values:
//    VNGERR_OUTBOX_FULL    - Senders sent messages quota exceeded
//    VNGERR_INVALID_LEN    -
//       nRecipients == 0 or recipients == NULL or results == NULL
//       nRecipients > VNG_MAX_STORE_MSG_N_RECIP
//       strlen() of any recipient[i] > VNG_MAX_LOGIN_LEN
//       strlen(subject) > VNG_MAX_SUBJECT_LEN
//       msgLen != 0 and msgBuffer == NULL
//       msgLen > VNG_MAX_STORED_MSG_LEN
//       VNG_MEDIA_TYPE_TEXT && msgLen != 0 and strlen(msgBuffer) > msgLen
//
// If mediaType is VNG_MEDIA_TYPE_TEXT and msgLen != 0, the content
// of msgBuffer must be a NULL terminated string.  msgLen must be
// large enough to include the terminating '\0' char.  The actual
// message length will be determined by the position of the first '\0'.
//

LIBVNG_API  VNGErrCode  VNG_StoreMessage (VNG           *vng,
                                          const char    *recipients[],
                                          uint32_t       nRecipients,
                                          const char    *subject,
                                          uint32_t       mediaType,
                                          const void    *msgBuffer,
                                          size_t         msgLen,
                                          uint32_t       replyMsgid,
                                          uint32_t      *results,
                                          VNGTimeout     timeout);

typedef struct {
    VNGTimeOfDay sendTime;
    uint32_t     msgId;
    char         subject[VNG_SUBJECT_BUF_SIZE];
    char         senderName[VNG_LOGIN_BUF_SIZE];
    char         recipientName[VNG_LOGIN_BUF_SIZE];
    uint32_t     status;   // non-zero means read by recipient
    uint32_t     mediaType;
    uint32_t     msgLen;
    uint32_t     replyMsgid;
} VNGMessageHdr;


// VNG_GetMessageList() gets a list of incoming messages.
//
//    skipN:    Skip the first N retrievable Message headers
//
//    msgHdr:   Pointer to a buffer to be filled with message headers.
//
//    nMsgHdr:  The max message headers to return in msgHdr[].  On return
//              it will indicate the number of returned message headers.
//
//    nMessages: The total number of messages available for retrieval.
//
// If on return, skipN + nMsgHdr < nMessages, there are additional
// message headers available.  To get the additional message headers
// make multiple calls with the skipN argument updated on each call
// to the number of message headers already retrieved.
//
// If an error code is returned,
//
//    nMsgHdr will be the number of headers successfully returned.
//
// If nMsgHdr is > VN_MAX_MSG_LEN / sizeof(VNGMessageHdr),
// VNG_GetMessageList() will make multiple requests to the infrastructure
// server to get the message headers requested.
//
// VNG_GetMessageList() specific error return values:
//    VNGERR_INVALID_ARG    -  msgHdr == NULL or nMsgHdr == NULL
//    VNGERR_INVALID_LEN    - *nMsgHdr == 0
//
// nMessages can be NULL.
//
LIBVNG_API  VNGErrCode  VNG_GetMessageList (VNG            *vng,
                                            uint32_t        skipN,     // in
                                            VNGMessageHdr  *msgHdr,    // out
                                            uint32_t       *nMsgHdr,   // in/out
                                            VNGTimeout      timeout);


// Retrieve the message indicated by msgId.
//
// Set msgLen to the max message size to return in msgBuffer.  On return
// it will indicate the size of the returned message.
//
// The msgId and message length can be obtaind from a VNGMessageHdr
// returned by a previous call to VNG_GetMessageList().
//
LIBVNG_API  VNGErrCode  VNG_RetrieveMessage (VNG        *vng,
                                             uint32_t    msgId,
                                             char       *msgBuffer,
                                             size_t     *msgLen,
                                             VNGTimeout  timeout);

// Delete one or more messages indicated in msgId[].
//
// nMsgId indicates the number of message ids in msgId[].
//
// The msgId can be obtaind from a VNGMessageHdr
// returned by a previous call to VNG_GetMessageList().
//
// VNG_DeleteMessage() specific error return values:
//     VNGERR_STM_DELETE   - The logged in user is not a recipient of
//                           one or more messages indicated in msgId[].
//     VNGERR_INVALID_LEN  - nMsgId != 0 and msgId == NULL
//
LIBVNG_API  VNGErrCode  VNG_DeleteMessage (VNG        *vng,
                                           uint32_t   *msgId,
                                           uint32_t    nMsgId,
                                           VNGTimeout  timeout);









//-----------------------------------------------------------
//-------------------------VNG  Events
//-----------------------------------------------------------

// An event is a notification to the user application when the
// VNG library detects a change of state,  such as the online
// status of the peer game player.   The events must be polled
// and processed by the user application.  In a multithreaded
// environment, the application may invoke the getEvent function
// as a blocking call by dedicating one thread for event handling.

// An event message contains an event-id, and an optional struct carrying
// a small amount of data about the event for efficient processing.
// Larger amount of data is accessed using a different VNG function call.

typedef enum {
    VNG_EVENT_BUDDY_STATUS = 1,
    VNG_EVENT_PEER_STATUS,
    VNG_EVENT_JOIN_REQUEST,
    VNG_EVENT_RECV_NOTIFY,
    VNG_EVENT_LOGOUT,
    VNG_EVENT_NEW_STORED_MSG,
} VNGEventID;

typedef struct {
    VNGUserId   uid;
} VNGEventBuddyStatus;

typedef struct {
    VN       *vn;
    VNMember  memb;
} VNGEventPeerStatus;

typedef struct {
    VNId      vnId;
} VNGEventJoinRequest;

// VNG_EVENT_RECV_INVITE informs that an invite to join a game sent
// via VNG_Invite is available to be retrieved via VNG_GetInvitation.
// Only the VNG pointer is needed to retrieve an invite. No data is
// provided with the event.
//
// An event is queued each time an invite to join a game is received.
// All VNG_EVENT_RECV_INVITE events in the queue are removed when
// the the last invitation is retrieved via VNG_GetInvitation.

// VNG_EVENT_LOGOUT is queued when the VNG login session terminates
// due to somwthing other than an explicit VNG_Logout.


typedef struct {
    VNGEventID eid;
    union {
            VNGEventBuddyStatus  buddyStatus;
            VNGEventPeerStatus    peerStatus;
            VNGEventJoinRequest  joinRequest;
    } evt;
} VNGEvent;


LIBVNG_API  VNGErrCode  VNG_GetEvent (VNG        *vng,
                                      VNGEvent   *event,
                                      VNGTimeout  timeout);



//-----------------------------------------------------------
//---------------- Blob encode/decode functions
//-----------------------------------------------------------

// When sending messages, sometimes it is advantageous to encode
// (marshal) data into a host-independent format, and when receiving
// messages the values must be decoded (un-marshaled).  While we
// do not provide support for encoding higher-level data structures
// or self-described tagging of values, we do provide a library of
// basic functions for converting host values to/from host independent
// byte sequences.
//
// All these functions return the number of bytes
// encoded/decoded, which is the same as the size of the host
// value, except for character strings which are encoded with
// a size-field of 2 bytes and are limited to a length of 64K bytes.
//
// The buffer to hold encoded integral values must be allocated
// to be large enough to hold the respective encoded values.
//
// Character strings are truncated to the available blob size
// upon encoding.  Decoding a character string fails if the buffer
// to hold the decoded string is too small.
//
// These functions return a size of zero (0) upon failure to
// encode or decode:

static inline size_t VNG_EncodeUint16(uint8_t *buffer, uint16_t v)
{
    buffer[1] = (uint8_t)(v & UINT32_C(0xff));        // Least significant
    buffer[0] = (uint8_t)((v >> 8) & UINT32_C(0xff)); // Most significant
    return sizeof(v);
}
static inline size_t VNG_EncodeUint32(uint8_t *buffer, uint32_t v)
{
    buffer[3] = (uint8_t)(v & UINT32_C(0xff));        // Least significant
    buffer[2] = (uint8_t)((v >> 8) & UINT32_C(0xff));
    buffer[1] = (uint8_t)((v >> 16) & UINT32_C(0xff));
    buffer[0] = (uint8_t)((v >> 24) & UINT32_C(0xff));// Most significant
    return sizeof(v);
}
static inline size_t VNG_EncodeUint64(uint8_t *buffer, uint64_t v)
{
    buffer[7] = (uint8_t)(v & UINT64_C(0xff));        // Least significant
    buffer[6] = (uint8_t)((v >> 8) & UINT64_C(0xff));
    buffer[5] = (uint8_t)((v >> 16) & UINT64_C(0xff));
    buffer[4] = (uint8_t)((v >> 24) & UINT64_C(0xff));
    buffer[3] = (uint8_t)((v >> 32) & UINT64_C(0xff));
    buffer[2] = (uint8_t)((v >> 40) & UINT64_C(0xff));
    buffer[1] = (uint8_t)((v >> 48) & UINT64_C(0xff));
    buffer[0] = (uint8_t)((v >> 56) & UINT64_C(0xff));// Most significant
    return sizeof(v);
}
static inline size_t VNG_EncodeInt16(uint8_t *buffer, int16_t i)
{
    return VNG_EncodeUint16(buffer, (uint16_t)i);
}
static inline size_t VNG_EncodeInt32(uint8_t *buffer, int32_t i)
{
    return VNG_EncodeUint32(buffer, (uint32_t)i);
}
static inline size_t VNG_EncodeInt64(uint8_t *buffer, int64_t i)
{
    return VNG_EncodeUint64(buffer, (uint64_t)i);
}

#if !defined(VNG_NO_INLINE_STRNLEN) && (defined(_WIN32))
    static inline size_t strnlen(const char *s, size_t maxlen)
    {
        const char *p = s;
        const char *e = s + maxlen;
        while (p != e && *p)
            ++p;

        return p - s;
    }
#else
    size_t strnlen(const char *s, size_t maxlen);
#endif


static inline size_t VNG_EncodeStr(uint8_t     *buffer,
                                    size_t      buffer_sz,
                                    const char *str)
{
    const size_t sz = strnlen(str, buffer_sz);
    if (sz+2 > buffer_sz || sz > (size_t)UINT16_MAX)
        return 0;
    else {
        VNG_EncodeUint16(buffer, (uint16_t)sz);
        memcpy(buffer+2, str, sz);
        return sz+2;
    }
}



static inline size_t VNG_DecodeUint16(const uint8_t *enc, uint16_t *i)
{
    // Decode netorder bytes
    //
    *i = (uint16_t)(((uint32_t)enc[0] << 8) + (uint32_t)enc[1]);
    return sizeof(*i);
}
static inline size_t VNG_DecodeUint32(const uint8_t *enc, uint32_t *i)
{
    // Decode netorder bytes
    //
    *i = (((uint32_t)enc[0] << 24) +
            ((uint32_t)enc[1] << 16) +
            ((uint32_t)enc[2] << 8)  +
            (uint32_t)enc[3]);
    return sizeof(*i);
}
static inline size_t VNG_DecodeUint64(const uint8_t *enc, uint64_t *i)
{
    // Decode netorder bytes
    //
    *i = (((uint64_t)enc[0] << 56) +
            ((uint64_t)enc[1] << 48) +
            ((uint64_t)enc[2] << 40) +
            ((uint64_t)enc[3] << 32) +
            ((uint64_t)enc[4] << 24) +
            ((uint64_t)enc[5] << 16) +
            ((uint64_t)enc[6] << 8)  +
            (uint64_t)enc[7]);
    return sizeof(*i);
}
static inline size_t VNG_DecodeInt16(const uint8_t *enc, int16_t *i)
{
    return VNG_DecodeUint16(enc, (uint16_t*)i);
}
static inline size_t VNG_DecodeInt32(const uint8_t *enc, int32_t *i)
{
    return VNG_DecodeUint32(enc, (uint32_t*)i);
}
static inline size_t VNG_DecodeInt64(const uint8_t *enc, int64_t *i)
{
    return VNG_DecodeUint64(enc, (uint64_t*)i);
}
// returns size of blob decoded
// sets *strsize to size of char buffer required for str
static inline size_t VNG_DecodeStr (const uint8_t *enc,
                                    char          *str,
                                    size_t        *strsize)
{
    uint16_t     sz;
    const size_t szlen = VNG_DecodeUint16(enc, &sz);
    *strsize = sz + 1;
    if (sz < *strsize) {
        memcpy(str, enc + szlen, sz);
        str[sz] = '\0';
        return sz + szlen;
    }
    else {
        return 0;
    }
}


#if !defined(_GBA) && !defined(_SC)
#pragma pack(pop)
#endif



#ifdef __cplusplus
}
#endif //__cplusplus

#include "vng_priv.h"

#endif // __VNG_H__


