Files @ ec90f545efc5
Branch filter:

Location: DistRen/src/common/request.h

binki
Fix random warnings.
/*
 * 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 <http://www.gnu.org/licenses/>.
 */

#ifndef _DISTREN_REQUEST_H
#define _DISTREN_REQUEST_H

#include "common/protocol.h"

#include <openssl/sha.h>

/**
 * @file functions to initialize various requests that the server and
 * client may both use.
 */


/**
 * Free any request made with one of the functions below
 */
int distren_request_free_with_data(struct distren_request *req, void *data);

/**
 * Initialize a VERSION request.
 *
 * @param req pointer to where the poitner to the new req should be stored..
 * @param data pointer to where the newly allocated data's address should go.
 * @param servertype the ORing of different DISTREN_SERVERTYPE_* constants.
 * @param package_string the PACKAGE_STRING constant.
 */
int distren_request_version(struct distren_request **req, void **data, uint32_t servertype, const char *package_string);

/**
 * Parses a DISTREN_REQUEST_VERSION packet.
 *
 * @param req the request to parse.
 * @param data the request's data.
 * @param version where the result should be stored.
 * @return 0 on success, 1 if the packet is invalid (if the length of package_version is longer than 32-bytes, for example).
 */
int distren_request_parse_version(struct distren_request *req, void *data, struct distren_request_version *version);

/**
 * Initialize a PASS request so as to identify to a server.
 *
 * \param req Where to store the newly allocated req.
 * \param data Where to store the newly allocated data.
 * \param user The username to send to the server.
 * \param pass The password to send to the server.
 */
int distren_request_pass(struct distren_request **req, void **data, const char *username, const char *pass);

/**
 * Initialize a PING or PONG request.
 *
 * @param data a place to allocate storage for the data associated with this request
 * @param is_ping 1 if this is a DISTREN_REQUEST_PING or 0 if this is a DISTREN_REQUEST_PONG
 * @param poing_cookie chocolate chip, chocolate chunk, or oatmeal chocolate chip
 * @param poing_data_len bytes in the poing_cookie
 * @return the length of the data allocated for this request
 */
int distren_request_poing(struct distren_request **req, void **data, short is_ping, const void *poing_cookie, size_t poing_data_len);

struct distren_request_file_post_context;
typedef struct distren_request_file_post_context *distren_request_file_post_context_t;

/**
 * Frees a post_context for if a client is disconnected or an upload
 * otherwise interrupted.
 */
int distren_request_file_post_context_free(distren_request_file_post_context_t post_context);

/**
 * Prepares for a file upload and initializes a
 * distren_request_file_post_context_t.
 *
 * If you call this function and you never finish an upload, you
 * _must_ call distren_request_file_post_finish() on post_context at
 * least to free the post_context.
 *
 * @param req where to store the new distren_request pointer.
 * @param data where to store the new request's data pointer. 
 * @param post_context where the newly allocated distren_request_file_post_context_t's addrss should be stored.
 * @param post_id a number that uniquely identifies this upload for this connection.
 * @param filename a user-friendly filename for the file posting.
 */
int distren_request_file_post_start(struct distren_request **req,
				    void **data,
				    distren_request_file_post_context_t *post_context,
				    uint32_t post_id,
				    const char *filename);

/**
 * Parses a DISTREN_REQUEST_FILE_POST_START request.
 *
 * @param req the recieved request.
 * @param data the request's data.
 * @param post_context a post_context to be initialized for a continued download. Must be free()d with a call to distren_request_parse_file_post_finish() or distren_request_file_post_context_free(), however.
 * @param post_id will be set to the post_id contained in the packet.
 * @param filename will be made to point at the filename the client requested. *filename must be free()d.
 * @return 0 upon no problem, 1 if there's an error. If 1, then *filename should not be used (it will be set NULL, so no problem calling free() on it though).
 */
int distren_request_parse_file_post_start(struct distren_request *req,
					  void *data,
					  distren_request_file_post_context_t *post_context,
					  uint32_t *post_id,
					  char **filename);

/**
 * Initializes a DISTREN_REQUEST_FILE_POST packet's header.
 *
 * As file posting requires an acceptable chunk of memory, we don't
 * malloc() the data portion of the packet here to encourage reading
 * files in through static buffers.
 *
 * As a single file takes multiple DISTREN_REQUEST_FILE_POST packets
 * before it's completely uploaded, certain state information has to
 * persist between calls to distren_request_file_post(). This is what
 * the post_context argument is for. This pointer must be preserved
 * between calls to distren_request_file_post().
 *
 * @param req place to store the new req's pointer
 * @param data_header where the data's header should be stored
 * @param post_context what this points to must be preserved between calls to distren_request_file_post(), for keeping state.
FILE_POST_DATA_LEN.
 * @param data a hunk of the file being posted.
 * @param len the length of the data argument. This must be less than or equal to DISTREN_REQUEST_ */
int distren_request_file_post(struct distren_request **req,
			      struct distren_request_file_post *data_header,
			      distren_request_file_post_context_t post_context,
			      const void *data,
			      size_t len);

/**
 * A callback to find a distren_request_file_post_context_t for a
 * specified post_id.
 *
 * This exists because it is recognized that two servers may be
 * transfering more than one file at a time between eachother. At the
 * time that distren_request_parse_file_post() is called, the caller
 * doesn't know post_id and thus can't provide the proper
 * post_context. Yet distren_request_parse_file_post() needs the
 * post_context to get its job done ;-).
 *
 * @param post_id the post_id for which to find a distren_request_file_post_context_t
 * @param find_post_context_data the same find_post_context_data pointer passed to distren_request_parse_file_post() or distren_request_parse_file_post_finish().
 * @return NULL if the context could not be found or the context.
 */
typedef distren_request_file_post_context_t(*distren_request_parse_file_post_find_context_func_t)(uint32_t post_id, void *find_post_context_data);

/**
 * Parse a DISTREN_REQUEST_FILE_POST packet and update the
 * post_context.
 *
 * @param req the request header.
 * @param data the request data section.
 * @param post_id will be filled with the request's post_id.
 * @param find_context_func a function that can look up the necessary context_post given a post_id.
 * @param find_post_context_data the pointer to pass as context data to find_context_func
 * @param file_data will be set to the beginning of the file data portion of the packet. Do not free() this pointer.
 * @param file_data_len the number of bytes of file data that may be accessed at *file_data.
 * @return 0 on success and 1 on failure, in which case the client should be kicked and you should free the post_context with distren_request_file_post_context_free().
 */
int distren_request_parse_file_post(struct distren_request *req,
				    void *data,
				    uint32_t *post_id,
				    distren_request_parse_file_post_find_context_func_t find_context_func,
				    void *find_post_context_data,
				    void **file_data,
				    size_t *file_data_len);

/**
 * Construct a packet signalling that a file posting is finished.
 *
 * Frees the memory used to store the post_context. Must be called
 * once for every call to distren_request_file_post_start(),
 * regardless of whether or not you actually call
 * distren_request_send() on the result.
 *
 * @param req where to store the pointer of the newly allocated request
 * @param data where to store the pointer t othe newly allocated request data
 * @param post_context the post_context which will be used and then freed.
 * @param cancel 0 if the file was uploaded successfully, 1 if the upload is cancelled or failed. 
 */
int distren_request_file_post_finish(struct distren_request **req,
				     void **data,
				     distren_request_file_post_context_t post_context,
				     uint32_t cancel);

/**
 * Parses a DISTREN_REQUEST_FILE_POST_FINISH packet.
 *
 * You must still call distren_request_file_post_context_free() on the
 * post_context which you must find yourself. If you are a server, you
 * must keep a list of these contexts per-client so that when a client
 * exits, you may reclaim these contexts.
 *
 * @param req the request header
 * @param data the data section of the packet
 * @param post_id a place where the post_id will be set.
 * @param find_context_func a function pointer to let me find a post_context based on the post_id of the request.
 * @param find_post_context_data the pointer to pass to the find_context_func callback.
 * @return 0 for a good packet, 1 for a bad packet or if the post_context can't be found (post_id won't be valid), 2 if the request asks for the user to cancel the file upload (post_id will be valid), and 3 if the checksums don't match (post_id will be valid).
 */
int distren_request_parse_file_post_finish(struct distren_request *req,
				    void *data,
				    uint32_t *post_id,
				    distren_request_parse_file_post_find_context_func_t find_context_func,
				    void *find_post_context_data);
#endif /* _DISTREN_REQUEST_H */