/** * Try to retrieve data from the buffer associate with the file descriptor. * The read buffer is filled if required. If a complete message is available * it is returned. The message is passed through amsg_verify before it is * returned. * * @param fd The file descriptor to read a message from. * @return A complete message in malloced memory or NULL if there is no * data or only an incomplete message. If this function returns NULL, * it is guaranteed that data must be read from the file descriptor * before a complete message can be returned. It is not guaranteed * that all available data from the file descriptor was actuall read! */ struct anoubisd_msg * get_msg(int fd) { struct msg_buf *mbp; struct anoubisd_msg *msg; struct anoubisd_msg *msg_r; int copy; if ((mbp = _get_mbp(fd)) == NULL) { log_warnx("msg_buf not initialized"); return NULL; } if (mbp->rmsg) { if ((int)mbp->rmsgoff != mbp->rmsg->size) if (!_fill_buf(mbp)) goto eof; if ((int)mbp->rmsgoff == mbp->rmsg->size) { msg_r = mbp->rmsg; mbp->rmsg = NULL; mbp->rmsgoff = 0; goto message; } return NULL; } /* we need at least the struct anoubisd_msg structure. */ if (mbp->rtailp - mbp->rheadp < (int)sizeof(struct anoubisd_msg)) if (!_fill_buf(mbp)) goto eof; if (mbp->rtailp - mbp->rheadp < (int)sizeof(struct anoubisd_msg)) return NULL; /* check for a complete message */ msg = (struct anoubisd_msg *)mbp->rheadp; if (msg->size > MSG_SIZE_LIMIT || msg->size < (int)sizeof(struct anoubisd_msg)) { log_warnx("get_msg: Bad message size %d", msg->size); master_terminate(); } if ((msg_r = malloc(msg->size)) == NULL) { log_warn("get_msg: can't allocate memory"); master_terminate(); } copy = mbp->rtailp - mbp->rheadp; if (copy > msg->size) copy = msg->size; memcpy(msg_r, msg, copy); mbp->rheadp += copy; if (msg_r->size != copy) { mbp->rmsg = msg_r; mbp->rmsgoff = copy; return NULL; } message: amsg_verify(msg_r); DEBUG(DBG_MSG_RECV, "get_msg: fd:%d size:%d", mbp->fd, msg_r->size); return msg_r; eof: return NULL; }
/* Поскольку точное время жизненно важно для хранилища, то обращаться с ним следует следующим образом: - проведем базовую проверку сравнив в временем компиляции и установим time_good если проверка пройдена. - ждем, пока появится время GPS, - проведем коррекцию. Если время RTC в прошлом - то просто добавим разницу к текущему значению, в противном случае сбросим флаг time_good, будем ждать, пока время GPS не догонит системное. Если разница больше чем STORAGE_VOID_LIMIT_US - обнулим хранилище и начнем с начала. */ bool_t bnapStorageDoRecord(BnapStorage_t *bsp){ bool_t status; int64_t timestamp = -1; /* there is no sense to do something without normal time */ if (GlobalFlags.time_good != 1) return CH_FAILED; if (GlobalFlags.time_proved == 1){ timestamp = fastGetTimeUnixUsec(); if (bsp->mtime > timestamp){ if (bsp->mtime > (timestamp + STORAGE_VOID_LIMIT_US)){/* time too far in future */ bnapStorageWipe(bsp); } return CH_FAILED; /* wait until mtime be older than current system time */ } } _fill_buf(bsp->buf, ×tamp); status = bsp->mmcp->vmt->write(bsp->mmcp, bsp->tip, bsp->buf, 1); chDbgCheck(status == CH_SUCCESS, "write failed"); bsp->tip++; if (bsp->tip >= bsp->mmcp->capacity) bsp->tip = 0; /* wrap ring buffer */ bsp->used++; if (bsp->used >= bsp->mmcp->capacity) bsp->used = bsp->mmcp->capacity; /* clamp value */ bsp->mtime = timestamp; return CH_SUCCESS; }
/** * Read an anoubis protocol message from a client connected to the session * engine. A client message on the wire consists of a 32 bit length in * network byte order followed by the actual message data. The length * given includes the 32 length itself and the 32 bit checksum at the * end of the message. * * @param fd The file descriptor to read from. * @param msgp A complete message (if any) is stored here. This value * must never be NULL. The pointer pointed to by msgp is either set * to NULL or is set to point to the result message. The result message * is allocated using anoubis_msg_new and must be freed by the caller * with anoubis_msg_free. * @return Zero if EOF is encountered. A negative error code if an error * occured or a positive value in case of success. * NOTE: Success does not mean that there is a complete message * available. The message may still be incomplete. In this case * NULL is stored in *msgp. */ int get_client_msg(int fd, struct anoubis_msg **msgp) { struct msg_buf *mbp; u_int32_t len; struct anoubis_msg *m; *msgp = NULL; if ((mbp = _get_mbp(fd)) == NULL) return 0; if (mbp->rmsg) { log_warnx("get_client_msg: Bad buffer state"); return 0; } if ((unsigned int)(mbp->rtailp - mbp->rheadp) < sizeof(len)) if (!_fill_buf(mbp)) return 0; if ((unsigned int)(mbp->rtailp - mbp->rheadp) < sizeof(len)) return 1; len = ntohl(*(u_int32_t*)mbp->rheadp); if ((unsigned int)(mbp->rtailp - mbp->rheadp) < len) if (!_fill_buf(mbp)) return 0; if ((unsigned int)(mbp->rtailp - mbp->rheadp) < len) return 1; /* * anoubis_msg_new expects the size of the message without * the message length and without the trainling checksum (i.e. * payload data only). However, m->length of the resulting * message includes the checksum but not the message length. * This is the reason for the somewhat surprising length calculations. */ m = anoubis_msg_new(len - sizeof(len) - CSUM_LEN); if (!m) return -ENOMEM; memcpy(m->u.buf, mbp->rheadp+sizeof(len), m->length); mbp->rheadp += len; *msgp = m; return 1; }