/* This file is part of GNUnet GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_core.h * @brief The APIs to the GNUnet core. See also core.c. * @author Christian Grothoff */ #ifndef COREAPI_H #define COREAPI_H #include "gnunet_util.h" /** * Just the version number of GNUnet-core API. * Encoded as * 0.6.1d => 0x00060100 * 4.5.2 => 0x04050200 * * Note that this version number is only changed if * something changes in the core API. It follows * roughly the main GNUnet version scheme, but is * more a compatibility ID. */ #define GNUNET_CORE_VERSION 0x00060500 /** * Priority for special administrative messages that * for example overrules drop-rules. */ #define EXTREME_PRIORITY 0xFFFFFF /** * Opaque handle for a session representation on the transport * layer side */ typedef struct { unsigned short ttype; void * internal; } TSession; /** * A session is a token provided by the transport * API to refer to a connection of the transport * layer. */ typedef struct { /** * To whom are we connected with this session? */ HostIdentity sender; /** * The transport type for this session. */ unsigned short ttype; /** * The MTU for this session. */ unsigned short mtu; /** * Is this session encrypted (send only)? */ int isEncrypted; /** * The session handle specific for the transport service. */ TSession * tsession; } Session; /** * HELO. * A HELO body contains the current HostAddress, * the host identity (hash), the time how long the * HostAddress is valid, a signature signing the * information above and the public key of the host. * The hash of the public key must match the host * identity.
* The signature goes over the message starting at
* the HostIdentity and includes the senderAddress.
* Since the senderAddress may be long, what is
* actually signed is the hash of these bytes.
*/
typedef struct {
p2p_HEADER header;
/**
* The signature
*/
Signature signature;
/**
* The public key
*/
PublicKey publicKey;
/**
* Whose identity follows? No, this is NOT a duplicate
* as a node may send us the identity of ANOTHER node!
*/
HostIdentity senderIdentity;
/**
* time this address expires (network byte order)
*/
TIME_T expirationTime;
/**
* size of the sender address
*/
unsigned short senderAddressSize;
/**
* protocol supported by the node (only one protocol
* can be advertised by the same HELO)
* Examples are UDP, TCP, etc. This field is
* in network byte order
*/
unsigned short protocol;
/**
* advertised MTU for sending (replies can have a different
* MTU!)
*/
unsigned int MTU;
} HELO_Message;
typedef struct {
HELO_Message helo_message;
/**
* address of the node in a protocol specific format
*/
char senderAddress[1];
} HELO_Message_GENERIC;
#define HELO_Message_size(helo) ((sizeof(HELO_Message) + ntohs((helo)->senderAddressSize)))
/**
* Type of a handler for messages from clients.
*/
typedef int (*CSHandler)(ClientHandle client,
const CS_HEADER * message);
/**
* Type of a struct passed to receive.
*/
typedef struct {
/**
* The session associated with the message
* on the transport layer side. Maybe passed to "associate"
* in order to send replies on a bi-directional pipe (if
* possible).
*/
TSession * tsession;
/**
* The identity of the sender node
*/
HostIdentity sender;
/**
* The message itself. The GNUnet core will call 'xfree' once
* processing of msg is complete. Note that msg can point to
* multiple p2p_headers.
*/
p2p_HEADER * msg;
/**
* The size of the message
*/
unsigned int size;
/**
* YES if the message was encrypted, NO otherwise
* (LOOPBACK is a special value for messages that are
* to be treated as encrypted except that they are in plaintext)
*/
int isEncrypted;
/**
* The checksum of the message (over size bytes from msg)
*/
int crc;
} MessagePack;
#define LOOPBACK 3
/**
* This header file contains a draft for the gnunetd
* core API. This API is used by the transport layer
* for communication with the GNUnet core.
*
* A pointer to an instance of this struct is passed
* to the init method of each Transport API.
*/
typedef struct {
/**
* The version of the CORE API. For now, always "0".
*/
unsigned int version;
/**
* The identity of the local node.
*/
HostIdentity * myIdentity;
/**
* Data was received (potentially encrypted), make
* the core process it.
*
* @param mp the message, freed by the callee once processed!
*/
void (*receive)(MessagePack * mp);
} CoreAPIForTransport;
typedef void (*ClientExitHandler)(ClientHandle client);
/**
* Type of a handler for some message type.
*/
typedef int (*MessagePartHandler)(const HostIdentity * sender,
const p2p_HEADER * message);
/**
* Type of a handler for some message type.
* @param identity the id of the node
*/
typedef void (*PerNodeCallback)(const HostIdentity * identity,
void * data);
/**
* Type of a send callback to fill up buffers.
* @param receiver the receiver of the message
* @param position is the reference to the
* first unused position in the buffer where GNUnet is building
* the message
* @param padding is the number of bytes left in that buffer.
* @return the number of bytes written to
* that buffer (must be a positive number).
*/
typedef int (*BufferFillCallback)(const HostIdentity * receiver,
void * position,
int padding);
/**
* Callback that is used to fill in a message into the send buffer.
* Note that the size of the message was specified when the callback
* was installed.
*
* @param buf pointer to the buffer where to copy the msg to
* @param closure context argument that was given when the callback was installed
* @param len the expected number of bytes to write to buf
* @return OK on success, SYSERR on error
*/
typedef int (*BuildMessageCallback)(void * buf,
void * closure,
unsigned short len);
/**
* Ping message (test if address actually corresponds to
* the advertised GNUnet host. The receiver responds with
* exactly the same message, except that it is now a pong.
* This message can be send in plaintext and without padding
* and typically does make little sense (except keepalive)
* for an encrypted (authenticated) tunnel.
*
* There is also no proof that the other side actually
* has the acclaimed identity, the only thing that is
* proved is that the other side can be reached via
* the underlying protocol and that it is a GNUnet node.
*
* The challenge prevents an inept adversary from sending
* us a HELO and then an arbitrary PONG reply (adversary
* must at least be able to sniff our outbound traffic).
*/
typedef struct {
p2p_HEADER header;
/**
* Which peer is the target of the ping? This is important since for
* plaintext-pings, we need to catch faulty advertisements that
* advertise a correct address but with the wrong public key.
*/
HostIdentity receiver;
/**
* The challenge is a (pseudo) random number that an adversary that
* wants to fake a pong message would have to guess. Since even if
* the number is guessed, the security impact is at most some wasted
* resources, 32 bit are more than enough.
*/
int challenge;
} PINGPONG_Message;
/**
* Message fragment.
*/
typedef struct {
p2p_HEADER header;
/**
* Fragment identity.
*/
int id;
/**
* Fragment offset.
*/
unsigned short off;
/**
* Total fragment size
*/
unsigned short len;
} FRAGMENT_Message;
/**
* Message fragment.
*/
typedef struct {
FRAGMENT_Message fragment_message;
char data[1];
} FRAGMENT_Message_GENERIC;
/**
* GNUnet CORE API for applications and services that are implemented
* on top of the GNUnet core.
*/
typedef struct {
/**
* The version of the CORE API. For now, always "0".
*/
unsigned int version;
/**
* The identity of the local node.
*/
HostIdentity * myIdentity;
/**
* Ping a host an call a method if a reply comes back.
* @param receiverIdentity the identity to fill into the ping
* @param method the method to call if a PONG comes back
* @param data an argument to pass to the method.
* @param pmsg the ping-message, pingAction just fills it in,
* the caller is responsbile for sending it!
* @returns OK on success, SYSERR on error
*/
int (*pingAction)(const HostIdentity * receiver,
CronJob method,
void * data,
PINGPONG_Message * pmsg);
/**
* Sign a message with the key of the local node.
* @param message the message to sign
* @param size the size of the message
* @param sig where to store the signature
* @return OK on success, SYSERR on error
* (typically size negative or to large)
*/
int (*sign)(void * message,
unsigned short size,
Signature * sig);
/**
* @param signer the identity of the host that presumably signed the message
* @param message the signed message
* @param size the size of the message
* @param sig the signature
* @return OK on success, SYSERR on error (verification failed)
*/
int (*verifySig)(const HostIdentity * signer,
void * message,
int size,
Signature * sig);
/**
* Increase the preference for traffic from some other peer.
* @param node the identity of the other peer
* @param preference how much should the traffic preference be increased?
*/
void (*preferTrafficFrom)(const HostIdentity * node,
double preference);
/**
* Query how much bandwidth is availabe FROM the given node to
* this node in bpm (at the moment).
*/
unsigned int (*queryBPMfromPeer)(const HostIdentity * node);
/**
* Change our trust in some other node.
* @param node the identity of the node
* @param delta by how much to change the trust
* @return the actual change in trust (trust can not go negative,
* so if the existing trust was 6 and delta was -10, then
* changeTrust will return -6.
*/
unsigned int (*changeTrust)(const HostIdentity * node,
int delta);
/**
* Get the amount of trust that we have in a node.
*/
unsigned int (*getTrust)(const HostIdentity * node);
/**
* Send an encrypted message to another node.
* @param receiver the target node
* @param msg the message to send
* @param importance how important is the message?
* @param maxdelay how long can the message be delayed?
*/
void (*sendToNode)(const HostIdentity * receiver,
const p2p_HEADER * msg,
unsigned int importance,
unsigned int maxdelay);
/**
* Send a message to the client identified by the handle. Note that
* the core will typically buffer these messages as much as possible
* and only return SYSERR if it runs out of buffers. Returning OK
* on the other hand does NOT confirm delivery since the actual
* transfer happens asynchronously.
*/
SendToClientCallback sendToClient;
/**
* Send a message to the client identified by the handle. Note that
* the core will typically buffer these messages as much as possible
* and only return SYSERR if it runs out of buffers. Returning OK
* on the other hand does NOT confirm delivery since the actual
* transfer happens asynchronously.
*/
int (*sendTCPResultToClient)(ClientHandle handle,
int value);
/**
* Send an encrypted, on-demand build message to another node.
* @param receiver the target node
* @param callback the callback to build the message
* @param closure the second argument to callback
* @param len how long is the message going to be?
* @param importance how important is the message?
* @param maxdelay how long can the message wait?
*/
void (*unicast)(const HostIdentity * receiver,
BuildMessageCallback callback,
void * closure,
unsigned short len,
unsigned int importance,
unsigned int maxdelay);
/**
* Perform an operation for all connected hosts.
* The BufferEntry structure is passed to the method.
* No synchronization or other checks are performed.
*
* @param method the method to invoke (NULL for counting only)
* @param arg the second argument to the method
* @return the number of connected hosts
*/
int (*forAllConnectedNodes)(PerNodeCallback method,
void * arg);
/**
* Send a message to all connected nodes. Note that this is
* not a network-wide broadcast!
* @param msg the message to send
* @param importance how important is the message?
* @param maxdelay how long can we wait (max), in seconds
*/
void (*broadcastToConnected)(const p2p_HEADER * msg,
unsigned int importance,
unsigned int maxdelay);
/**
* Register a callback method that should be invoked whenever a message
* is about to be send that has more than minimumPadding bytes left
* before maxing out the MTU.
* The callback method can then be used to add additional content
* to the message (instead of the random noise that is added by
* otherwise). Note that if the MTU is 0 (for streams), the
* callback method will always be called with padding set to the
* maximum number of bytes left in the buffer allocated for the
* send.
* @param minimumPadding how large must the padding be in order
* to call this method?
* @param callback the method to invoke. The receiver is the
* receiver of the message, position is the reference to the
* first unused position in the buffer where GNUnet is building
* the message, padding is the number of bytes left in that buffer.
* The callback method must return the number of bytes written to
* that buffer (must be a positive number).
* @return OK if the handler was registered, SYSERR on error
*/
int (*registerSendCallback)(const unsigned int minimumPadding,
BufferFillCallback callback);
/**
* Unregister a handler that was registered with registerSendCallback.
* @return OK if the handler was removed, SYSERR on error
*/
int (*unregisterSendCallback)(const unsigned int minimumPadding,
BufferFillCallback callback);
/**
* Register a method as a handler for specific message
* types.
* @param type the message type
* @param callback the method to call if a message of
* that type is received
* @return OK on success, SYSERR if there is already a
* handler for that type
*/
int (*registerClientHandler)(const unsigned short type,
CSHandler callback);
/**
* Return wheter or not there is a method handler
* registered for a specific Client-Server message type.
* @param the message type
* @return YES if there is a handler for the type,
* NO if there isn't
*/
int (*isClientHandlerRegistered)(const unsigned short type);
/**
* Remove a method as a handler for specific message
* types.
* @param type the message type
* @param callback the method to call if a message of
* that type is received
* @return OK on success, SYSERR if there is a different
* handler for that type
*/
int (*unregisterClientHandler)(const unsigned short type,
CSHandler callback);
/**
* Register a handler to call if any client exits.
* @param callback a method to call with the socket
* of every client that disconnected.
* @return OK on success, SYSERR on error
*/
int (*registerClientExitHandler)(ClientExitHandler callback);
/**
* Unregister a handler to call if any client exits.
* @param callback a method to call with the socket
* of every client that disconnected.
* @return OK on success, SYSERR on error
*/
int (*unregisterClientExitHandler)(ClientExitHandler callback);
/**
* Register a method as a handler for specific message
* types. Only for encrypted messages!
* @param type the message type
* @param callback the method to call if a message of
* that type is received
* @return OK on success, SYSERR if there is already a
* handler for that type
*/
int (*registerHandler)(const unsigned short type,
MessagePartHandler callback);
/**
* Return wheter or not there is a method handler
* registered for a specific message type.
* @param the message type
* @return YES if there is a handler for the type,
* NO if there isn't
*/
int (*isHandlerRegistered)(const unsigned short type);
/**
* Unregister a method as a handler for specific message
* types. Only for encrypted messages!
* @param type the message type
* @param callback the method to call if a message of
* that type is received
* @return OK on success, SYSERR if there is a different
* handler for that type
*/
int (*unregisterHandler)(const unsigned short type,
MessagePartHandler callback);
/**
* Return the estimated size of the network in
* the number of nodes running at the moment.
*/
int (*estimateNetworkSize)();
/**
* Compute the index (small, positive, pseudo-unique identification
* number) of a hostId.
*/
unsigned int (*computeIndex)(const HostIdentity * hostId);
/**
* The the lock of the connection module. A module that registers
* callbacks may need this.
*/
Mutex * (*getConnectionModuleLock)();
/**
* Get statistics over the number of messages that
* were received or send of a given type.
*
* @param messageType the type of the message
* @param sendReceive TC_SEND for sending, TC_RECEIVE for receiving
* @param timePeriod how many TRAFFIC_TIME_UNITs to take
* into consideration (limited by HISTORY_SIZE)
* @param avgMessageSize average size of the messages (set)
* @param messageCount number of messages (set)
* @param peerCount number of peers engaged (set)
* @param timeDistribution bit-vector giving times of interactions,
* highest bit is current time-unit, bit 1 is 32 time-units ago (set)
* @return OK on success, SYSERR on error
*/
int (*getTrafficStats)(const unsigned short messageType,
const int sendReceive,
const unsigned int timePeriod,
unsigned short * avgMessageSize,
unsigned short * messageCount,
unsigned int * peerCount,
unsigned int * timeDistribution);
/**
* Obtain the public key and address of a known host. If no specific
* protocol is specified (ANY_PROTOCOL_NUMBER), HELOs for cheaper
* protocols are returned with preference (randomness!).
*
* @param hostId the host id
* @param protocol the protocol that we need,
* ANY_PROTOCOL_NUMBER if we do not care which protocol
* @param tryTemporaryList is it ok to check the unverified HELOs?
* @param result where to store the result
* @returns SYSERR on failure, OK on success
*/
int (*identity2Helo)(const HostIdentity * hostId,
const unsigned short protocol,
int tryTemporaryList,
HELO_Message ** result);
/**
* Bind a host addres (helo) to a hostId.
* @param msg the verified (!) HELO message
*/
void (*bindAddress)(HELO_Message * msg);
/**
* Disconnect a particular peer. Send a HANGUP message to the other side
* and mark the sessionkey as dead.
*
* @param peer the peer to disconnect
*/
void (*disconnectFromPeer)(const HostIdentity *peer);
/**
* Disconnect all current connected peers. Send HANGUP messages to the other peers
* and mark the sessionkeys as dead.
*
*/
void (*disconnectPeers)();
/**
* Load an application module. This function must be called
* while cron is suspended. Note that the initialization and
* shutdown function of modules are always run while cron is
* disabled, so suspending cron is not necesary if modules
* are loaded or unloaded inside the module initialization or
* shutdown code.
*
* @return OK on success, SYSERR on error
*/
int (*loadApplicationModule)(const char * name);
/**
* Unload an application module. This function must be called
* while cron is suspended. Note that the initialization and
* shutdown function of modules are always run while cron is
* disabled, so suspending cron is not necesary if modules
* are loaded or unloaded inside the module initialization or
* shutdown code.
*
* @return OK on success, SYSERR on error
*/
int (*unloadApplicationModule)(const char * name);
/**
* Which percentage of inbound messages should gnunetd drop at
* random (to simulate network unreliability or congestion).
*/
void (*setPercentRandomInboundDrop)(int value);
/**
* Which percentage of outbound messages should gnunetd drop at
* random (to simulate network unreliability or congestion).
*/
void (*setPercentRandomOutboundDrop)(int value);
/**
* Load a service module of the given name. This function must be
* called while cron is suspended. Note that the initialization and
* shutdown function of modules are always run while cron is
* disabled, so suspending cron is not necesary if modules are
* loaded or unloaded inside the module initialization or shutdown
* code.
*/
void * (*requestService)(const char * name);
/**
* Notification that the given service is no longer required. This
* function must be called while cron is suspended. Note that the
* initialization and shutdown function of modules are always run
* while cron is disabled, so suspending cron is not necesary if
* modules are loaded or unloaded inside the module initialization
* or shutdown code.
*
* @return OK if service was successfully released, SYSERR on error
*/
int (*releaseService)(void * service);
/**
* Terminate the connection with the given client (asynchronous
* detection of a protocol violation).
*/
void (*terminateClientConnection)(ClientHandle handle);
} CoreAPIForApplication;
/**
* Type of the initialization method implemented by GNUnet protocol
* plugins.
*
* @param capi the core API
*/
typedef int (*ApplicationInitMethod) (CoreAPIForApplication * capi);
/**
* Type of the shutdown method implemented by GNUnet protocol
* plugins.
*/
typedef void (*ApplicationDoneMethod)();
/**
* Type of the initialization method implemented by GNUnet service
* plugins.
*
* @param capi the core API
*/
typedef void * (*ServiceInitMethod)(CoreAPIForApplication * capi);
/**
* Type of the shutdown method implemented by GNUnet service
* plugins.
*/
typedef void (*ServiceDoneMethod)();
#endif