Files
@ e0b7e9dd5b54
Branch filter:
Location: DistRen/src/common/request.h
e0b7e9dd5b54
9.6 KiB
text/plain
File uploads are now supported using DISTREN_REQUEST_FILE_POST and friends.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 | /*
* 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 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 */
|