/*
Copyright 2010 Nathan Phillip Brink
This file is a part of DistRen.
DistRen is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
DistRen 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with DistRen. If not, see .
*/
#ifndef DISTREN_PROTOCOL_H
#define DISTREN_PROTOCOL_H
#include
#include
/**
* Server types:
*
* It is assumed that any client has at least the functionality of a
* normal client (i.e., accepts all of the REQUIRED requests). These
* bitmask values add to the types of requests one may make to a
* server. After first connecting to a server or receiving a
* connection, a client shall send a DISTREN_REQUEST_VERSION packet
* describing its version.
*/
#define DISTREN_SERVERTYPE_SUBMIT (0x1)
#define DISTREN_SERVERTYPE_DISTRIBUTE (0x2)
#define DISTREN_SERVERTYPE_RENDER (0x4)
#define DISTREN_SERVERTYPE_CLIENT (0x8)
/**
* This file defines the constants and structs that distren clients
* and server use to converse.
*/
/**
* List of request types and metadata.
*/
enum distren_request_type
{
/**
* identifies the version of software being used by the sender and
* tells if it is a client or server. Sends PACKAGE_STRING as well
* as informing the other server what type of server this is.
*
* DATA: struct distren_request followed by PACKAGE_STRING. The length of PACKAGE_STRING must be no longer than 32 bytes.
*
* REQUIRED: ALL
*/
DISTREN_REQUEST_VERSION = 1,
/**
* DATA: up to 32 bytes of a PING cookie
*
* REQUIRED: ALL
*/
DISTREN_REQUEST_PING = 2,
/**
* DATA: up to 32 bytes copied from a received PING cookie
*
* REQUIRED: ALL
*/
DISTREN_REQUEST_PONG = 3,
/**
* The data is the a reason describing why the one end is
* disconnecting. The other end should respectfully close()
* the socket or the sender will timeout shortly.
*
* DATA: A string describing the reason for the connection's
* termination.
*
* REQUIRED: ALL
*/
DISTREN_REQUEST_DISCONNECT = 4,
/**
* DATA: struct distren_request_submit
*
* REQUIRED: DISTREN_SERVERTYPE_SUBMIT
*/
DISTREN_REQUEST_SUBMIT = 5,
/**
* Inform the other party about a job.
*
* DATA: struct distren_request_jobinfo
*
* REQUIRED: ALL
*/
DISTREN_REQUEST_JOBINFO = 6,
/**
* Request a DISTREN_REQUEST_JOBINFO
*
* DATA: struct distren_request_jobinfo_get
*
* REQUIRED: DISTREN_SERVERTYPE_SUBMIT, DISTREN_SERVERTYPE_DISTRIBUTE
*/
DISTREN_REQUEST_JOBINFO_GET = 7,
/**
* Command the other party to render a frame
*
* DATA: struct distren_request_frame_render
*
* REQUIRED: DISTREN_SERVERTYPE_RENDER
*/
DISTREN_REQUEST_FRAME_RENDER = 8,
/**
* Inform the receiver of the sender's state, such as frames being
* rendered or jobs that need to be completed.
*
* DATA: struct distren_request_status
*
* REQUIRED: DISTREN_SERVERTYPE_RENDER, DISTREN_SERVERTYPE_DISTRIBUTE, DISTREN_SERVERTYPE_CLIENT
*/
DISTREN_REQUEST_STATUS = 9,
/**
* Request that the receiver send a DISTREN_REQUEST_FRAME_STATUS
* packet. No data because the sending party might not beforehand
* know what frames/jobs the receiving server is managing.
*
* DATA: (none)
*
* REQUIRED: DISTREN_SERVERTYPE_RENDER
*/
DISTREN_REQUEST_STATUS_GET = 10,
/**
* Allow a client to upload a job tarball over a remoteio line. A
* client that wants to do this must take care not to overbuffer
* his sendqueue so as to be able to respond to PING packets in
* time. A server receiving such a message will want to write the
* file as directly to disk as possible to avoid bagging a server
* down in swap.
*
* It is potential that if a server is DISTREN_SERVERTYPE_SUBMIT
* but not also DISTREN_SERVERTYPE_DISTRIBUTE, that this request
* would be relayed by the DISTREN_SERVERTYPE_SUBMIT server to a
* DISTREN_SERVERTYPE_DISTRIBUTE server so that other clients can
* obtain the file from the distribution server. In this case, the
* file's URL is already known.
*
* Of course, having this sort of functionality at all is where
* the nasty security issues start coming into play :-D.
*
* DATA: struct distren_request_file_post followed by a maximum of 131072 bytes (128kB).
*
* REQUIRED: DISTREN_SERVERTYPE_SUBMIT, DISTREN_SERVERTYPE_DISTRIBUTE
*/
DISTREN_REQUEST_FILE_POST = 11,
/**
* Request information about obtaining a file (such as a
* cURL-compatible URL) based on a distren file URL.
*
* DATA: struct distren_request_file_find
*
* REQUIRED: DISTREN_SERVERTYPE_DISTRIBUTE
*/
DISTREN_REQUEST_FILE_FIND = 12,
/**
* Provide information about obtaining a file (such as a URL).
*
* DATA: struct distren_request_file
*
* REQUIRED: DISTREN_SERVERTYPE_DISTRIBUTE
*/
DISTREN_REQUEST_FILE = 13,
};
struct distren_request
{
uint32_t magic;
/* the length of the data associated with the packet excluding the header */
uint32_t len;
/** treat type as an enum distren_request_type using casting */
uint32_t /* enum distren_request_type */ type;
};
#define DISTREN_REQUEST_VERSION_PACKAGE_STRING_LEN (32)
/**
* A DISTREN_REQUEST_VERSION is started with a bitmask specification
* of the DISTREN_SERVERTYPE_* values.
*/
struct distren_request_version
{
uint32_t servertype;
/* + 1 is for terminating NULL */
char package_string[DISTREN_REQUEST_VERSION_PACKAGE_STRING_LEN + 1];
};
/**
* initializes and allocates request
*/
int distren_request_new(struct distren_request **req, uint32_t len, enum distren_request_type type);
struct remoteio;
/**
Takes a struct distren_request and its associated data, allocates
a new block of data to hold the whole packet, and packets the req
header and data together.
@param rem A remoteio handle to ship this packet off to
@param req Something you initialized with distren_request_new(). You are responsible for distren_request_free()ing this yourself.
@param data A chunk of data the size of req->len. You are responsible for free()ing this yourself.
@return 0 on success and 1 on failure.
*/
int distren_request_send(struct remoteio *rem, struct distren_request *req, void *data);
/**
* initializes and allocates request based on raw input data
* which includes the headers of the request.
*
* @return 0 on success, 1 on failure
*/
int distren_request_new_fromdata(struct distren_request **req, void *data, size_t len);
/**
* Parses requests in a way suitable to be called from a
* remoteio_read_handle_func_t.
*
* If this function returns non-zero, you should handle the request
* and then call this function again (after shortening len and
* incrementing buf, of course).
*
* @param expectlen A pointer to a state variable that, if not NULL, can speed up this function. If you want to use this, you must set the variable to 0 before the first call and preserve the variable.
* @param buf the input buffer.
* @param len the length of buf.
* @param req a pointer to where we should set NULL if we don't have a full request or where we store the address of a newly allocated request. You should call distren_request_free() on this.
* @param req_data a pointer to where the request data pointer should be stored. This will just be set to a pointer in buf, so don't free() this.
* @param err this will be set to 0 if there is no error and to 1 if there is an error and the connection should be closed. You must check this.
* @return number of bytes that we have used from buf and that should be marked used.
*/
size_t distren_request_handle(size_t *expectlen,
void *buf,
size_t len,
struct distren_request **req,
void **req_data,
short *err);
/**
* frees request
*/
int distren_request_free(struct distren_request *req);
/**
* An implementation of remoteio_read_handle_func_t for use with remoteio.
*
* To use this handler, first initialize a struct distren_request_remoteio_data.
* (to be continued... or not...? ;-) )
*/
/* size_t distren_request_remoteio_handle(struct remoteio *rem, void *generic_data, void *buf, size_t len, void *data); */
#endif