This just-committed change prepares for a more significant protocol change later on (variable-length keys in requests). This is a network protocol change, though a minor one you probably won't notice, due to the chunksrv_req/chunksrv_resp structures currently being twins (that will soon change). commit 69cf0ae597fd83086c1746a02c776b0bc05d591e Author: Jeff Garzik <jeff@xxxxxxxxxx> Date: Wed Nov 4 16:44:34 2009 -0500 Clone chunksrv_req into new chunksrv_resp, to separate request and response messages. - resp_code removed from chunksrv_req - s/checksum/sig/ in chunksrv_req - req_len() used to calculate request size (preparation for future) - resp_init_req() used to init response from request, rather than memcpy() - improve data-in debugging Signed-off-by: Jeff Garzik <jgarzik@xxxxxxxxxx> diff --git a/include/chunk_msg.h b/include/chunk_msg.h index 610f8c5..4222f27 100644 --- a/include/chunk_msg.h +++ b/include/chunk_msg.h @@ -10,6 +10,7 @@ enum { CHD_USER_SZ = 64, CHD_KEY_SZ = 64, CHD_CSUM_SZ = 64, + CHD_SIG_SZ = 64, }; enum chunksrv_ops { @@ -37,6 +38,17 @@ enum errcode { struct chunksrv_req { uint8_t magic[CHD_MAGIC_SZ]; /* CHUNKD_MAGIC */ uint8_t op; /* CHO_xxx */ + uint8_t rsv1[3]; + uint32_t nonce; /* random number, to stir checksum */ + uint64_t data_len; /* len of addn'l data */ + char user[CHD_USER_SZ]; /* username */ + char key[CHD_KEY_SZ]; /* object id */ + char sig[CHD_SIG_SZ]; /* HMAC signature */ +}; + +struct chunksrv_resp { + uint8_t magic[CHD_MAGIC_SZ]; /* CHUNKD_MAGIC */ + uint8_t op; /* CHO_xxx */ uint8_t resp_code; /* errcode's */ uint8_t rsv1[2]; uint32_t nonce; /* random number, to stir checksum */ @@ -47,7 +59,7 @@ struct chunksrv_req { }; struct chunksrv_resp_get { - struct chunksrv_req req; + struct chunksrv_resp resp; uint64_t mtime; }; diff --git a/include/chunksrv.h b/include/chunksrv.h index f9f7abc..6cae18a 100644 --- a/include/chunksrv.h +++ b/include/chunksrv.h @@ -3,6 +3,7 @@ #include <chunk_msg.h> +extern size_t req_len(const struct chunksrv_req *req); extern void chreq_sign(struct chunksrv_req *req, const char *key, char *b64hmac_out); diff --git a/lib/chunkdc.c b/lib/chunkdc.c index 121b589..9c00b8c 100644 --- a/lib/chunkdc.c +++ b/lib/chunkdc.c @@ -216,7 +216,7 @@ static size_t all_data_cb(void *ptr, size_t size, size_t nmemb, void *user_data) static bool stc_get_req(struct st_client *stc, const char *key, uint64_t *plen) { struct chunksrv_req req; - struct chunksrv_resp_get resp; + struct chunksrv_resp_get get_resp; if (stc->verbose) fprintf(stderr, "libstc: GET(%s)\n", key); @@ -230,28 +230,29 @@ static bool stc_get_req(struct st_client *stc, const char *key, uint64_t *plen) strcpy(req.key, key); /* sign request */ - chreq_sign(&req, stc->key, req.checksum); + chreq_sign(&req, stc->key, req.sig); /* write request */ - if (!net_write(stc, &req, sizeof(req))) + if (!net_write(stc, &req, req_len(&req))) return false; /* read response header */ - if (!net_read(stc, &resp, sizeof(resp.req))) + if (!net_read(stc, &get_resp, sizeof(get_resp.resp))) return false; /* check response code */ - if (resp.req.resp_code != Success) { + if (get_resp.resp.resp_code != Success) { if (stc->verbose) - fprintf(stderr, "GET resp code: %d\n", resp.req.resp_code); + fprintf(stderr, "GET resp code: %d\n", get_resp.resp.resp_code); return false; } /* read rest of response header */ - if (!net_read(stc, &resp.mtime, sizeof(resp) - sizeof(resp.req))) + if (!net_read(stc, &get_resp.mtime, + sizeof(get_resp) - sizeof(get_resp.resp))) return false; - *plen = le64_to_cpu(resp.req.data_len); + *plen = le64_to_cpu(get_resp.resp.data_len); return true; } @@ -330,7 +331,7 @@ bool stc_get_start(struct st_client *stc, const char *key, int *pfd, * return a -EPIPE (normally not possible on read in UNIX). Fortunately, * applications know the object lengths as reported by stc_get_start. */ -size_t stc_get_recv(struct st_client *stc, void *data, size_t req_len) +size_t stc_get_recv(struct st_client *stc, void *data, size_t data_len) { size_t xfer_len; size_t done_cnt; @@ -340,7 +341,7 @@ size_t stc_get_recv(struct st_client *stc, void *data, size_t req_len) done_cnt = 0; if (stc->ssl) { for (;;) { - if (done_cnt == req_len) + if (done_cnt == data_len) break; if (ioctl(stc->fd, FIONREAD, &avail)) return errno; @@ -349,8 +350,8 @@ size_t stc_get_recv(struct st_client *stc, void *data, size_t req_len) break; } - if ((xfer_len = avail) > req_len - done_cnt) - xfer_len = req_len - done_cnt; + if ((xfer_len = avail) > data_len - done_cnt) + xfer_len = data_len - done_cnt; rc = SSL_read(stc->ssl, data + done_cnt, xfer_len); if (rc <= 0) { @@ -371,8 +372,8 @@ size_t stc_get_recv(struct st_client *stc, void *data, size_t req_len) if (ioctl(stc->fd, FIONREAD, &avail)) return errno; if (avail) { - if ((xfer_len = avail) > req_len) - xfer_len = req_len; + if ((xfer_len = avail) > data_len) + xfer_len = data_len; rc = read(stc->fd, data, xfer_len); if (rc < 0) @@ -390,7 +391,7 @@ bool stc_put(struct st_client *stc, const char *key, { char netbuf[4096]; struct chunksrv_req req; - struct chunksrv_req resp; + struct chunksrv_resp resp; uint64_t content_len = len; if (stc->verbose) @@ -407,10 +408,10 @@ bool stc_put(struct st_client *stc, const char *key, strcpy(req.key, key); /* sign request */ - chreq_sign(&req, stc->key, req.checksum); + chreq_sign(&req, stc->key, req.sig); /* write request */ - if (!net_write(stc, &req, sizeof(req))) + if (!net_write(stc, &req, req_len(&req))) goto err_out; while (content_len) { @@ -477,10 +478,10 @@ bool stc_put_start(struct st_client *stc, const char *key, uint64_t cont_len, strcpy(req.key, key); /* sign request */ - chreq_sign(&req, stc->key, req.checksum); + chreq_sign(&req, stc->key, req.sig); /* write request */ - if (!net_write(stc, &req, sizeof(req))) + if (!net_write(stc, &req, req_len(&req))) goto err_out; *pfd = stc->fd; @@ -545,7 +546,7 @@ size_t stc_put_send(struct st_client *stc, void *data, size_t len) */ bool stc_put_sync(struct st_client *stc) { - struct chunksrv_req resp; + struct chunksrv_resp resp; /* read response header */ if (!net_read(stc, &resp, sizeof(resp))) @@ -597,7 +598,7 @@ bool stc_put_inline(struct st_client *stc, const char *key, bool stc_del(struct st_client *stc, const char *key) { struct chunksrv_req req; - struct chunksrv_resp_get resp; + struct chunksrv_resp resp; if (stc->verbose) fprintf(stderr, "libstc: DEL(%s)\n", key); @@ -611,20 +612,20 @@ bool stc_del(struct st_client *stc, const char *key) strcpy(req.key, key); /* sign request */ - chreq_sign(&req, stc->key, req.checksum); + chreq_sign(&req, stc->key, req.sig); /* write request */ - if (!net_write(stc, &req, sizeof(req))) + if (!net_write(stc, &req, req_len(&req))) return false; /* read response header */ - if (!net_read(stc, &resp, sizeof(resp.req))) + if (!net_read(stc, &resp, sizeof(resp))) return false; /* check response code */ - if (resp.req.resp_code != Success) { + if (resp.resp_code != Success) { if (stc->verbose) - fprintf(stderr, "DEL resp code: %d\n", resp.req.resp_code); + fprintf(stderr, "DEL resp code: %d\n", resp.resp_code); return false; } @@ -722,7 +723,7 @@ struct st_keylist *stc_keys(struct st_client *stc) GByteArray *all_data; char netbuf[4096]; struct chunksrv_req req; - struct chunksrv_resp_get resp; + struct chunksrv_resp resp; uint64_t content_len; if (stc->verbose) @@ -736,20 +737,20 @@ struct st_keylist *stc_keys(struct st_client *stc) strcpy(req.user, stc->user); /* sign request */ - chreq_sign(&req, stc->key, req.checksum); + chreq_sign(&req, stc->key, req.sig); /* write request */ - if (!net_write(stc, &req, sizeof(req))) + if (!net_write(stc, &req, req_len(&req))) return false; /* read response header */ - if (!net_read(stc, &resp, sizeof(resp.req))) + if (!net_read(stc, &resp, sizeof(resp))) return false; /* check response code */ - if (resp.req.resp_code != Success) { + if (resp.resp_code != Success) { if (stc->verbose) - fprintf(stderr, "LIST resp code: %d\n", resp.req.resp_code); + fprintf(stderr, "LIST resp code: %d\n", resp.resp_code); return false; } @@ -757,7 +758,7 @@ struct st_keylist *stc_keys(struct st_client *stc) if (!all_data) return NULL; - content_len = le64_to_cpu(resp.req.data_len); + content_len = le64_to_cpu(resp.data_len); /* read response data */ while (content_len) { @@ -822,7 +823,7 @@ err_out: bool stc_ping(struct st_client *stc) { struct chunksrv_req req; - struct chunksrv_resp_get resp; + struct chunksrv_resp resp; if (stc->verbose) fprintf(stderr, "libstc: PING\n"); @@ -835,20 +836,20 @@ bool stc_ping(struct st_client *stc) strcpy(req.user, stc->user); /* sign request */ - chreq_sign(&req, stc->key, req.checksum); + chreq_sign(&req, stc->key, req.sig); /* write request */ - if (!net_write(stc, &req, sizeof(req))) + if (!net_write(stc, &req, req_len(&req))) return false; /* read response header */ - if (!net_read(stc, &resp, sizeof(resp.req))) + if (!net_read(stc, &resp, sizeof(resp))) return false; /* check response code */ - if (resp.req.resp_code != Success) { + if (resp.resp_code != Success) { if (stc->verbose) - fprintf(stderr, "NOP resp code: %d\n", resp.req.resp_code); + fprintf(stderr, "NOP resp code: %d\n", resp.resp_code); return false; } diff --git a/lib/chunksrv.c b/lib/chunksrv.c index 4f6cfb7..d6482b2 100644 --- a/lib/chunksrv.c +++ b/lib/chunksrv.c @@ -5,6 +5,11 @@ #include <glib.h> #include <chunk_msg.h> +size_t req_len(const struct chunksrv_req *req) +{ + return sizeof(*req); +} + void chreq_sign(struct chunksrv_req *req, const char *key, char *b64hmac_out) { unsigned int len = 0; diff --git a/server/chunkd.h b/server/chunkd.h index d2418d1..8e666e7 100644 --- a/server/chunkd.h +++ b/server/chunkd.h @@ -256,6 +256,8 @@ extern bool cli_write_start(struct client *cli); extern int cli_req_avail(struct client *cli); extern int cli_poll_mod(struct client *cli); extern bool srv_poll_del(int fd); +extern void resp_init_req(struct chunksrv_resp *resp, + const struct chunksrv_req *req); /* config.c */ extern void read_config(void); diff --git a/server/object.c b/server/object.c index f49cd63..0792b66 100644 --- a/server/object.c +++ b/server/object.c @@ -21,7 +21,7 @@ bool object_del(struct client *cli) int rc; enum errcode err = InternalError; bool rcb; - struct chunksrv_req *resp = NULL; + struct chunksrv_resp *resp = NULL; resp = malloc(sizeof(*resp)); if (!resp) { @@ -29,7 +29,7 @@ bool object_del(struct client *cli) return true; } - memcpy(resp, &cli->creq, sizeof(cli->creq)); + resp_init_req(resp, &cli->creq); rcb = fs_obj_delete(cli->creq.user, obj_key, strnlen(obj_key, CHD_KEY_SZ), &err); @@ -66,7 +66,7 @@ static bool object_put_end(struct client *cli) int rc; enum errcode err = InternalError; bool rcb; - struct chunksrv_req *resp = NULL; + struct chunksrv_resp *resp = NULL; resp = malloc(sizeof(*resp)); if (!resp) { @@ -74,7 +74,7 @@ static bool object_put_end(struct client *cli) return true; } - memcpy(resp, &cli->creq, sizeof(cli->creq)); + resp_init_req(resp, &cli->creq); cli->state = evt_recycle; @@ -92,7 +92,7 @@ static bool object_put_end(struct client *cli) cli_out_end(cli); if (debugging) - applog(LOG_DEBUG, "REQ(write) seq %x done code %d", + applog(LOG_DEBUG, "REQ(data-in) seq %x done code %d", resp->nonce, resp->resp_code); rc = cli_writeq(cli, resp, sizeof(*resp), cli_cb_free, resp); @@ -113,13 +113,19 @@ bool cli_evt_data_in(struct client *cli, unsigned int events) { char *p = cli->netbuf; ssize_t avail, bytes; + size_t read_sz; if (!cli->out_len) return object_put_end(cli); + read_sz = MIN(cli->out_len, CLI_DATA_BUF_SZ); + + if (debugging) + applog(LOG_DEBUG, "REQ(data-in) seq %x, out_len %ld, read_sz %u", + cli->creq.nonce, cli->out_len, read_sz); + if (cli->ssl) { - int rc = SSL_read(cli->ssl, cli->netbuf, - MIN(cli->out_len, CLI_DATA_BUF_SZ)); + int rc = SSL_read(cli->ssl, cli->netbuf, read_sz); if (rc <= 0) { if (rc == 0) { cli->state = evt_dispose; @@ -139,8 +145,7 @@ bool cli_evt_data_in(struct client *cli, unsigned int events) } avail = rc; } else { - avail = read(cli->fd, cli->netbuf, - MIN(cli->out_len, CLI_DATA_BUF_SZ)); + avail = read(cli->fd, cli->netbuf, read_sz); if (avail <= 0) { if (avail == 0) { applog(LOG_ERR, "object read(2) unexpected EOF"); @@ -148,8 +153,11 @@ bool cli_evt_data_in(struct client *cli, unsigned int events) return true; } - if (errno == EAGAIN) + if (errno == EAGAIN) { + if (debugging) + applog(LOG_ERR, "object read(2) EAGAIN"); return false; + } cli_out_end(cli); applog(LOG_ERR, "object read(2) error: %s", @@ -158,9 +166,8 @@ bool cli_evt_data_in(struct client *cli, unsigned int events) } } - if (debugging) - applog(LOG_DEBUG, "REQ(write) seq %x avail %ld", - cli->creq.nonce, (long)avail); + if (debugging && (avail != read_sz)) + applog(LOG_DEBUG, "REQ(data-in) avail %ld", (long)avail); while (avail > 0) { bytes = fs_obj_write(cli->out_bo, p, avail); @@ -274,33 +281,33 @@ bool object_get(struct client *cli, bool want_body) int rc; enum errcode err = InternalError; struct backend_obj *obj; - struct chunksrv_resp_get *resp = NULL; + struct chunksrv_resp_get *get_resp = NULL; - resp = malloc(sizeof(*resp)); - if (!resp) { + get_resp = calloc(1, sizeof(*get_resp)); + if (!get_resp) { cli->state = evt_dispose; return true; } - memcpy(resp, &cli->creq, sizeof(cli->creq)); + resp_init_req(&get_resp->resp, &cli->creq); cli->in_obj = obj = fs_obj_open(cli->creq.user, obj_key, strnlen(obj_key, CHD_KEY_SZ), &err); if (!obj) { - free(resp); + free(get_resp); return cli_err(cli, err, true); } cli->in_len = obj->size; - resp->req.data_len = cpu_to_le64(obj->size); - memcpy(resp->req.checksum, obj->hashstr, sizeof(obj->hashstr)); - resp->req.checksum[sizeof(obj->hashstr)] = 0; - resp->mtime = cpu_to_le64(obj->mtime); + get_resp->resp.data_len = cpu_to_le64(obj->size); + memcpy(get_resp->resp.checksum, obj->hashstr, sizeof(obj->hashstr)); + get_resp->resp.checksum[sizeof(obj->hashstr)] = 0; + get_resp->mtime = cpu_to_le64(obj->mtime); - rc = cli_writeq(cli, resp, sizeof(*resp), cli_cb_free, resp); + rc = cli_writeq(cli, get_resp, sizeof(*get_resp), cli_cb_free, get_resp); if (rc) { - free(resp); + free(get_resp); return true; } diff --git a/server/server.c b/server/server.c index 878ec56..b2911b2 100644 --- a/server/server.c +++ b/server/server.c @@ -269,6 +269,18 @@ static bool srv_poll_mask(int fd, short mask_set, short mask_clear) return true; } +void resp_init_req(struct chunksrv_resp *resp, + const struct chunksrv_req *req) +{ + memset(resp, 0, sizeof(*resp)); + memcpy(resp->magic, req->magic, CHD_MAGIC_SZ); + resp->op = req->op; + resp->nonce = req->nonce; + resp->data_len = req->data_len; + strncpy(resp->user, req->user, CHD_USER_SZ); + strncpy(resp->key, req->key, CHD_KEY_SZ); +} + static bool cli_write_free(struct client *cli, struct client_write *tmp, bool done) { @@ -648,7 +660,7 @@ out: bool cli_err(struct client *cli, enum errcode code, bool recycle_ok) { int rc; - struct chunksrv_req *resp = NULL; + struct chunksrv_resp *resp = NULL; if (code != Success) applog(LOG_INFO, "client %s error %s", @@ -660,7 +672,7 @@ bool cli_err(struct client *cli, enum errcode code, bool recycle_ok) return true; } - memcpy(resp, &cli->creq, sizeof(cli->creq)); + resp_init_req(resp, &cli->creq); resp->resp_code = code; @@ -683,7 +695,7 @@ static bool cli_resp_xml(struct client *cli, GList *content) int rc; bool rcb; size_t content_len = strlist_len(content); - struct chunksrv_req *resp = NULL; + struct chunksrv_resp *resp = NULL; resp = malloc(sizeof(*resp)); if (!resp) { @@ -691,7 +703,7 @@ static bool cli_resp_xml(struct client *cli, GList *content) return true; } - memcpy(resp, &cli->creq, sizeof(cli->creq)); + resp_init_req(resp, &cli->creq); resp->data_len = cpu_to_le64(content_len); @@ -787,14 +799,14 @@ static bool authcheck(const struct chunksrv_req *req) char hmac[64]; memcpy(&tmpreq, req, sizeof(tmpreq)); - memset(&tmpreq.checksum, 0, sizeof(tmpreq.checksum)); + memset(&tmpreq.sig, 0, sizeof(tmpreq.sig)); /* for lack of a better authentication scheme, we * supply the username as the secret key */ chreq_sign(&tmpreq, req->user, hmac); - return strcmp(req->checksum, hmac) ? false : true; + return strcmp(req->sig, hmac) ? false : true; } static bool valid_req_hdr(const struct chunksrv_req *req) @@ -812,8 +824,8 @@ static bool valid_req_hdr(const struct chunksrv_req *req) if (len == sizeof(req->key)) return false; - len = strnlen(req->checksum, sizeof(req->checksum)); - if (len < 1 || len == sizeof(req->checksum)) + len = strnlen(req->sig, sizeof(req->sig)); + if (len < 1 || len == sizeof(req->sig)) return false; return true; @@ -912,7 +924,8 @@ static bool cli_evt_read_req(struct client *cli, unsigned int events) cli->req_ptr += rc; cli->req_used += rc; - if (cli->req_used < sizeof(cli->creq)) + /* poll for more, if fixed-length record not yet received */ + if (cli->req_used < sizeof(struct chunksrv_req)) return false; cli->state = evt_exec_req; -- To unsubscribe from this list: send the line "unsubscribe hail-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html